diff --git a/docs/references/ic-interface-spec/abstract-behavior.md b/docs/references/ic-interface-spec/abstract-behavior.md index 6ecb9f63..4f9b976a 100644 --- a/docs/references/ic-interface-spec/abstract-behavior.md +++ b/docs/references/ic-interface-spec/abstract-behavior.md @@ -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 aggregate metrics for a given subnet. 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 = + +``` + +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. diff --git a/docs/references/ic-interface-spec/changelog.md b/docs/references/ic-interface-spec/changelog.md index a225f33a..4159339d 100644 --- a/docs/references/ic-interface-spec/changelog.md +++ b/docs/references/ic-interface-spec/changelog.md @@ -8,6 +8,20 @@ sidebar: ## Changelog {#changelog} +### 0.69.0 (2026-09-17) {$0_69_0} +* New management canister method `subnet_metrics` returning a subnet's aggregate metrics + (`block_height`, `num_canisters`, `canister_state_bytes`, `consumed_cycles_total`, + `update_transactions_total`, and `million_round_instructions_total`) as an ordinary inter-canister + call, so that a canister can read them without a `read_state` call and a certificate to verify. + The method can only be called by canisters and is routed by the `subnet_id` in its argument, so a + canister can also read the metrics of a subnet other than its own. It is considered EXPERIMENTAL and + may evolve in a non-backward-compatible way. +* The field `million_round_instructions_total` of `subnet_metrics` reports the total number of + instructions the subnet accounted for across the execution phases of all rounds, in units of one + million and rounded up. Unlike the four aggregates of `subnet_metrics` it has no counterpart under + `/subnet//metrics` in the certified state tree, and its counter starts at zero when a + subnet's replica begins tracking it rather than at subnet creation. + ### 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 diff --git a/docs/references/ic-interface-spec/index.md b/docs/references/ic-interface-spec/index.md index 5a2b0935..cfbe7c8e 100644 --- a/docs/references/ic-interface-spec/index.md +++ b/docs/references/ic-interface-spec/index.md @@ -522,6 +522,8 @@ The state tree contains information about the topology of the Internet Computer. - `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. + The management canister method [`subnet_metrics`](./management-canister.md#ic-subnet_metrics) returns the same four metrics, plus two fields that have no path in the state tree, as an ordinary inter-canister call. A canister that does not need a certificate to verify them can read them that way instead. + :::note diff --git a/docs/references/ic-interface-spec/management-canister.md b/docs/references/ic-interface-spec/management-canister.md index e3723758..55008a02 100644 --- a/docs/references/ic-interface-spec/management-canister.md +++ b/docs/references/ic-interface-spec/management-canister.md @@ -849,6 +849,38 @@ 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 aggregate metrics for that subnet. The call is routed by the `subnet_id` in its argument, so a canister can read the metrics of a subnet other than its own. The subnet executing the call answers with its own metrics and rejects a `subnet_id` that does not match it. + +The fields returned are: + +- `block_height` (`nat`): the height of the block in whose execution this call is processed. It is monotonically non-decreasing for a given subnet; the heights of different subnets are unrelated. + +- `num_canisters` (`nat`): the number of canisters on the subnet. + +- `canister_state_bytes` (`nat`): the total size in bytes of the state taken by the canisters on the subnet. + +- `consumed_cycles_total` (`nat`): the total number of cycles consumed by all current and deleted canisters on the subnet. + +- `update_transactions_total` (`nat`): the total number of transactions processed on the subnet, i.e., the total number of messages executed in replicated mode. + +- `million_round_instructions_total` (`nat`): the total number of instructions the subnet accounted for across the execution phases of all rounds, counted in units of one million and rounded up (a value of `42` means 42 million instructions). Besides the executed Wasm instructions it also covers the fixed per-execution and per-canister overheads charged by the scheduler, and charges for work performed outside of Wasm execution (such as compilation, chunk assembly, and snapshot operations), so it is not a Wasm instruction meter. + +Only `block_height` is current as of the block in which the call is executed. The other five fields are read from the subnet's aggregated metrics, which the replica updates at the *end* of a round, so they are as of the end of the previous round. The field `canister_state_bytes` is staler still: it is only recomputed every 10 rounds (summing it over every canister is expensive and it does not need to be exact), so it can be up to ten rounds stale and reads as `0` for the first rounds after the subnet is created. + +The four aggregates `num_canisters`, `canister_state_bytes`, `consumed_cycles_total`, and `update_transactions_total` are the same values, with the same staleness, that `read_state` serves under the path `/subnet//metrics` (see [Subnet information](./index.md#state-tree-subnet)). The remaining two fields, `block_height` and `million_round_instructions_total`, have no path in the state tree, so unlike the aggregates their values cannot be verified against a certificate. The counter behind `million_round_instructions_total` also starts at zero when a subnet's replica begins tracking it, so on a subnet that predates the field it does not cover the rounds executed before that. + +No cycles are charged for the call, and serving it does not contribute to `million_round_instructions_total`. + ### 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. diff --git a/docs/references/management-canister.md b/docs/references/management-canister.md index 720826cf..1245c12e 100644 --- a/docs/references/management-canister.md +++ b/docs/references/management-canister.md @@ -589,6 +589,25 @@ 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 a subnet's aggregate metrics in a single inter-canister call, without the `read_state` call and certificate verification that reading them from the state tree requires. The call is routed by `subnet_id`, so a canister can also read another subnet's metrics. No cycles are charged for the call, and serving it does not add to `million_round_instructions_total`. + +- **Caller:** Canisters only +- **Parameters:** + - `subnet_id` (`principal`) +- **Returns:** + - `block_height` (`nat`): the height of the block in whose execution the call is processed + - `num_canisters` (`nat`): the number of canisters on the subnet + - `canister_state_bytes` (`nat`): the total size in bytes of the state taken by those canisters + - `consumed_cycles_total` (`nat`): the cycles consumed by all current and deleted canisters on the subnet + - `update_transactions_total` (`nat`): the messages executed in replicated mode on the subnet + - `million_round_instructions_total` (`nat`): the instructions the subnet accounted for across the execution phases of all rounds, in units of one million and rounded up + +Only `block_height` is current. The other fields are written at the end of a round, so they are as of the end of the previous round, and `canister_state_bytes` is only recomputed every 10 rounds. `million_round_instructions_total` counts the executed Wasm instructions plus the scheduler's per-execution and per-canister overheads and charges for work outside Wasm execution (compilation, chunk assembly, snapshots), 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 four aggregates are the same values the certified state tree serves under `/subnet//metrics`; `block_height` and `million_round_instructions_total` have no path there, so they cannot be verified against a certificate. + ### `subnet_info` Returns metadata about a subnet. diff --git a/public/references/ic.did b/public/references/ic.did index 8918b2fc..79011f9f 100644 --- a/public/references/ic.did +++ b/public/references/ic.did @@ -493,6 +493,19 @@ type node_metrics_history_result = vec record { node_metrics : vec node_metrics; }; +type subnet_metrics_args = record { + subnet_id : principal; +}; + +type subnet_metrics_result = record { + block_height : nat; + num_canisters : nat; + canister_state_bytes : nat; + consumed_cycles_total : nat; + update_transactions_total : nat; + million_round_instructions_total : nat; +}; + type subnet_info_args = record { subnet_id : principal; }; @@ -762,6 +775,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);