Skip to content

Commit fe646b2

Browse files
dsarlismraszyk
andauthored
feat: Add canister_metrics endpoint on management canister (#6217)
* feat: Add subnet admins capabilities * Update docs/references/ic-interface-spec.md Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com> * Review comments * Revert some change * Use or * feat: Add canister_metrics endpoint on management canister * Update docs/references/_attachments/ic.did Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com> * Review comments * Drop one level of indirection * Flatter structure * Drop threshold signature metrics * Review comments * metrics as query call * Update docs/references/ic-interface-spec.md Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com> * Merge master * Clarify when canister_metrics can be called * Move canister_metrics close to canister_status * Move canister_metrics close to canister_status in main doc too * Apply suggestions from code review Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com> * final touches * Update docs/references/ic-interface-spec.md * Update docs/references/ic-interface-spec.md --------- Co-authored-by: mraszyk <31483726+mraszyk@users.noreply.github.com>
1 parent 88f1fe0 commit fe646b2

3 files changed

Lines changed: 122 additions & 1 deletion

File tree

docs/references/_attachments/ic.did

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,30 @@ type upload_canister_snapshot_data_args = record {
630630
chunk : blob;
631631
};
632632

633+
type cycles_consumed = record {
634+
memory : nat;
635+
compute_allocation : nat;
636+
ingress_induction : nat;
637+
instructions : nat;
638+
request_and_response_transmission : nat;
639+
// This metric applies to canisters that ran out of cycles. In particular,
640+
// uninstalling code explicitly would not result in this metric being updated.
641+
// In fact, others might be updated in that case, e.g. cycles for ingress induction
642+
// if the uninstallation of the canister was requested via an ingress message.
643+
uninstall : nat;
644+
canister_creation : nat;
645+
http_outcalls : nat;
646+
burned_cycles : nat;
647+
};
648+
649+
type canister_metrics_args = record {
650+
canister_id : canister_id;
651+
};
652+
653+
type canister_metrics_result = record {
654+
cycles_consumed : cycles_consumed;
655+
};
656+
633657
service ic : {
634658
create_canister : (create_canister_args) -> (create_canister_result);
635659
update_settings : (update_settings_args) -> ();
@@ -642,6 +666,8 @@ service ic : {
642666
start_canister : (start_canister_args) -> ();
643667
stop_canister : (stop_canister_args) -> ();
644668
canister_status : (canister_status_args) -> (canister_status_result) query;
669+
// Returns canister related metrics
670+
canister_metrics: (canister_metrics_args) -> (canister_metrics_result) query;
645671
delete_canister : (delete_canister_args) -> ();
646672
deposit_cycles : (deposit_cycles_args) -> ();
647673
raw_rand : () -> (raw_rand_result);

docs/references/_attachments/interface-spec-changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## Changelog {#changelog}
22

3+
### 0.61.0 (2025-05-18) {$0_61_0}
4+
* New management canister endpoint `canister_metrics`.
5+
36
### 0.60.0 (2025-05-04) {$0_60_0}
47
* Canister signatures from canisters on subnets of type `cloud_engine` are not valid.
58
* New HTTP endpoints for update calls (to create a canister by subnet admins) and

docs/references/ic-interface-spec.md

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2712,6 +2712,22 @@ Only the controllers of the canister or the canister itself or subnet admins can
27122712

27132713
All sizes are expressed in bytes.
27142714

2715+
### IC method `canister_metrics` {#ic-canister_metrics}
2716+
2717+
This method can be called by canisters as well as by external users via ingress messages.
2718+
This method can also be called by external users via non-replicated (query) calls, but it cannot be called from composite query calls.
2719+
2720+
This method returns a set of canister related metrics for the requested canister, like cycles consumed by different use cases. These metrics should be counters (i.e. monotonically increasing values) that report the accumulated respective amount since the canister was created for new canisters or since the metrics introduction for existing canisters.
2721+
2722+
Only controllers of the canister or subnet admins can call this method.
2723+
2724+
:::warning
2725+
2726+
The response of a query comes from a single replica, and is therefore not appropriate for security-sensitive applications.
2727+
Replica-signed queries may improve security because the recipient can verify the response comes from the correct subnet.
2728+
2729+
:::
2730+
27152731
### IC method `canister_info` {#ic-canister_info}
27162732

27172733
This method can only be called by canisters, i.e., it cannot be called by external users via ingress messages.
@@ -4540,7 +4556,7 @@ liquid_balance(S, E.content.canister_id) ≥ 0
45404556
E.content.arg = candid({canister_id = CanisterId, …})
45414557
E.content.sender ∈ S.controllers[CanisterId] ∪ S.subnet_admins[S.canister_subnet[CanisterId]]
45424558
E.content.method_name ∈
4543-
{ "start_canister", "stop_canister", "uninstall_code", "delete_canister", "canister_status" }
4559+
{ "start_canister", "stop_canister", "uninstall_code", "delete_canister", "canister_status", "canister_metrics" }
45444560
) ∨ (
45454561
E.content.canister_id = ic_principal
45464562
E.content.sender ∈ S.subnet_admins[S.canister_subnet[ECID]]
@@ -7466,6 +7482,82 @@ S with
74667482

74677483
```
74687484

7485+
#### IC Management Canister: Canister metrics
7486+
7487+
Only the controllers of the given canister or subnet admins can get metrics about it.
7488+
7489+
```html
7490+
7491+
S.messages = Older_messages · CallMessage M · Younger_messages
7492+
(M.queue = Unordered) or (∀ msg Older_messages. msg.queue M.queue)
7493+
M.callee = ic_principal
7494+
M.method_name = 'canister_metrics'
7495+
M.arg = candid(A)
7496+
M.caller S.controllers[A.canister_id] S.subnet_admins[S.canister_subnet[A.canister_id]]
7497+
7498+
R = <implementation-specific>
7499+
7500+
```
7501+
7502+
State after
7503+
7504+
```html
7505+
7506+
S with
7507+
messages = Older_messages · Younger_messages ·
7508+
ResponseMessage {
7509+
origin = M.origin
7510+
response = Reply (candid(R))
7511+
refunded_cycles = M.transferred_cycles
7512+
}
7513+
7514+
```
7515+
7516+
The IC method `canister_metrics` can also be invoked via management canister query calls.
7517+
They are calls to `/api/v3/canister/<ECID>/query`
7518+
with CBOR content `Q` such that `Q.canister_id = ic_principal`.
7519+
7520+
Submitted request to `/api/v3/canister/<ECID>/query`
7521+
7522+
```html
7523+
7524+
E : Envelope
7525+
7526+
```
7527+
7528+
Conditions
7529+
7530+
```html
7531+
7532+
E.content = CanisterQuery Q
7533+
Q.canister_id = ic_principal
7534+
Q.method_name = 'canister_metrics'
7535+
|Q.nonce| <= 32
7536+
is_effective_canister_id(E.content, ECID)
7537+
S.system_time <= Q.ingress_expiry or Q.sender = anonymous_id
7538+
Q.arg = candid(A)
7539+
A.canister_id ∈ verify_envelope(E, Q.sender, S.system_time)
7540+
Q.sender ∈ S.controllers[A.canister_id] ∪ S.subnet_admins[S.canister_subnet[A.canister_id]]
7541+
7542+
```
7543+
7544+
Query response `R`:
7545+
7546+
```html
7547+
7548+
{status: "replied"; reply: {arg: candid(<implementation-specific>)}, signatures: Sigs}
7549+
7550+
```
7551+
7552+
where the query `Q`, the response `R`, and a certificate `Cert` that is obtained by requesting the path `/subnet` in a **separate** read state request to `/api/v3/canister/<ECID>/read_state` satisfy the following:
7553+
7554+
```html
7555+
7556+
verify_response(Q, R, Cert) ∧ lookup(["time"], Cert) = Found S.system_time // or "recent enough"
7557+
7558+
```
7559+
7560+
74697561
#### Callback invocation
74707562

74717563
When an inter-canister call has been responded to, we can queue the call to the callback.

0 commit comments

Comments
 (0)