Skip to content

Commit

Permalink
feat: add support for fetching the canister logs (#755)
Browse files Browse the repository at this point in the history
# Motivation

Add support for
[fetch_canister_logs](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-fetch_canister_logs).

# Changes

- Implement function `fetchCanisterLogs` in `ic-management`.

---------

Signed-off-by: David Dal Busco <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
peterpeterparker and github-actions[bot] authored Nov 20, 2024
1 parent 1782ef4 commit 7e4c1aa
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- Added `memoToNeuronSubaccount` and `memoToNeuronAccountIdentifier`.
- Support new neuron field `voting_power_refreshed_timestamp_seconds`.
- Add support for fetching the canister logs in `@dfinity@ic-management`.
- Add `nowInBigIntNanoSeconds` to `@dfinity/utils`, a trivial function that is actually used across all our dapps.

## Build
Expand Down
41 changes: 26 additions & 15 deletions packages/ic-management/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID);

### :factory: ICManagementCanister

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L30)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L33)

#### Methods

Expand All @@ -72,14 +72,15 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID);
- [canisterStatus](#gear-canisterstatus)
- [deleteCanister](#gear-deletecanister)
- [provisionalCreateCanisterWithCycles](#gear-provisionalcreatecanisterwithcycles)
- [fetchCanisterLogs](#gear-fetchcanisterlogs)

##### :gear: create

| Method | Type |
| -------- | ---------------------------------------------------------------- |
| `create` | `(options: ICManagementCanisterOptions) => ICManagementCanister` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L35)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L38)

##### :gear: createCanister

Expand All @@ -89,7 +90,7 @@ Create a new canister
| ---------------- | ------------------------------------------------------------------------------------- |
| `createCanister` | `({ settings, senderCanisterVersion, }?: CreateCanisterParams) => Promise<Principal>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L75)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L78)

##### :gear: updateSettings

Expand All @@ -99,7 +100,7 @@ Update canister settings
| ---------------- | ------------------------------------------------------------------------------------------- |
| `updateSettings` | `({ canisterId, senderCanisterVersion, settings, }: UpdateSettingsParams) => Promise<void>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L96)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L99)

##### :gear: installCode

Expand All @@ -109,7 +110,7 @@ Install code to a canister
| ------------- | ----------------------------------------------------------------------------------------------------- |
| `installCode` | `({ mode, canisterId, wasmModule, arg, senderCanisterVersion, }: InstallCodeParams) => Promise<void>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L118)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L121)

##### :gear: uploadChunk

Expand All @@ -124,7 +125,7 @@ Parameters:
- `params.canisterId`: The canister in which the chunks will be stored.
- `params.chunk`: A chunk of Wasm module.

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L143)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L146)

##### :gear: clearChunkStore

Expand All @@ -138,7 +139,7 @@ Parameters:

- `params.canisterId`: The canister in which the chunks are stored.

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L163)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L166)

##### :gear: storedChunks

Expand All @@ -152,7 +153,7 @@ Parameters:

- `params.canisterId`: The canister in which the chunks are stored.

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L182)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L185)

##### :gear: installChunkedCode

Expand All @@ -172,7 +173,7 @@ Parameters:
- `params.storeCanisterId`: Specifies the canister in whose chunk storage the chunks are stored (this parameter defaults to target_canister if not specified).
- `params.wasmModuleHash`: The Wasm module hash as hex string. Used to check that the SHA-256 hash of wasm_module is equal to the wasm_module_hash parameter and can calls install_code with parameters.

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L207)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L210)

##### :gear: uninstallCode

Expand All @@ -182,7 +183,7 @@ Uninstall code from a canister
| --------------- | -------------------------------------------------------------------------------- |
| `uninstallCode` | `({ canisterId, senderCanisterVersion, }: UninstallCodeParams) => Promise<void>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L240)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L243)

##### :gear: startCanister

Expand All @@ -192,7 +193,7 @@ Start a canister
| --------------- | ------------------------------------------ |
| `startCanister` | `(canisterId: Principal) => Promise<void>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L255)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L258)

##### :gear: stopCanister

Expand All @@ -202,7 +203,7 @@ Stop a canister
| -------------- | ------------------------------------------ |
| `stopCanister` | `(canisterId: Principal) => Promise<void>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L264)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L267)

##### :gear: canisterStatus

Expand All @@ -212,7 +213,7 @@ Get canister details (memory size, status, etc.)
| ---------------- | ------------------------------------------------------------ |
| `canisterStatus` | `(canisterId: Principal) => Promise<canister_status_result>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L273)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L276)

##### :gear: deleteCanister

Expand All @@ -222,7 +223,7 @@ Deletes a canister
| ---------------- | ------------------------------------------ |
| `deleteCanister` | `(canisterId: Principal) => Promise<void>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L284)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L287)

##### :gear: provisionalCreateCanisterWithCycles

Expand All @@ -232,7 +233,17 @@ Creates a canister. Only available on development instances.
| ------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `provisionalCreateCanisterWithCycles` | `({ settings, amount, canisterId, }?: ProvisionalCreateCanisterWithCyclesParams) => Promise<Principal>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L296)
[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L299)

##### :gear: fetchCanisterLogs

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, CQ, CRy, CRt, CC, and F modes, as defined in Overview of imports). 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. Logs persist across canister upgrades and they are deleted if the canister is reinstalled or uninstalled.

| Method | Type |
| ------------------- | ---------------------------------------------------------------- |
| `fetchCanisterLogs` | `(canisterId: Principal) => Promise<fetch_canister_logs_result>` |

[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L321)

<!-- TSDOC_END -->

Expand Down
53 changes: 52 additions & 1 deletion packages/ic-management/src/ic-management.canister.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import {
type StoredChunksParams,
type UploadChunkParams,
} from "./types/ic-management.params";
import { CanisterStatusResponse } from "./types/ic-management.responses";
import {
CanisterStatusResponse,
type FetchCanisterLogsResponse,
} from "./types/ic-management.responses";

describe("ICManagementCanister", () => {
const mockAgent: HttpAgent = mock<HttpAgent>();
Expand Down Expand Up @@ -667,4 +670,52 @@ describe("ICManagementCanister", () => {
expect(call).rejects.toThrowError(Error);
});
});

describe("fetchCanisterLogs", () => {
it("returns canister logs when success", async () => {
const settings = {
freezing_threshold: BigInt(2),
controllers: [mockPrincipal],
memory_allocation: BigInt(4),
compute_allocation: BigInt(10),
reserved_cycles_limit: BigInt(11),
log_visibility: { controllers: null },
wasm_memory_limit: BigInt(500_00),
};
const response: FetchCanisterLogsResponse = {
canister_log_records: [
{
idx: 123n,
content: [1, 2, 3],
timestamp_nanos: 12345n,
},
{
idx: 456n,
content: [9, 8, 7],
timestamp_nanos: 12346n,
},
],
};
const service = mock<IcManagementService>();
service.fetch_canister_logs.mockResolvedValue(response);

const icManagement = await createICManagement(service);

const res = await icManagement.fetchCanisterLogs(mockCanisterId);

expect(res).toEqual(response);
});

it("throws Error", async () => {
const error = new Error("Test");
const service = mock<IcManagementService>();
service.fetch_canister_logs.mockRejectedValue(error);

const icManagement = await createICManagement(service);

const call = () => icManagement.fetchCanisterLogs(mockCanisterId);

expect(call).rejects.toThrowError(Error);
});
});
});
18 changes: 17 additions & 1 deletion packages/ic-management/src/ic-management.canister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import {
type UpdateSettingsParams,
type UploadChunkParams,
} from "./types/ic-management.params";
import type { CanisterStatusResponse } from "./types/ic-management.responses";
import type {
CanisterStatusResponse,
FetchCanisterLogsResponse,
} from "./types/ic-management.responses";

export class ICManagementCanister {
private constructor(private readonly service: IcManagementService) {
Expand Down Expand Up @@ -308,4 +311,17 @@ export class ICManagementCanister {

return canister_id;
};

/**
* 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, CQ, CRy, CRt, CC, and F modes, as defined in Overview of imports). 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. Logs persist across canister upgrades and they are deleted if the canister is reinstalled or uninstalled.
*
* @param {Principal} canisterId
* @returns {Promise<FetchCanisterLogsResponse>}
*/
fetchCanisterLogs = (
canisterId: Principal,
): Promise<FetchCanisterLogsResponse> =>
this.service.fetch_canister_logs({
canister_id: canisterId,
});
}
5 changes: 5 additions & 0 deletions packages/ic-management/src/types/ic-management.responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ export type CanisterStatusResponse = ServiceResponse<
IcManagementService,
"canister_status"
>;

export type FetchCanisterLogsResponse = ServiceResponse<
IcManagementService,
"fetch_canister_logs"
>;

0 comments on commit 7e4c1aa

Please sign in to comment.