Introspection
Restate exposes information on invocations and application state via its CLI and Introspection SQL API. You can use this to gain insight into the status of invocations and the service state that is stored.
This can be useful for troubleshooting. For example, a Virtual Object might be blocked and you want to kill the invocation that is blocking it, but you don't know the invocation ID. Or you want to check what is currently stored in the state of a service.
- CLI
- psql
The CLI is the easiest way to get started with introspection.
Have a look at the installation guide for the CLI.
Restate exposes the following SQL tables, queryable via the psql client:
sys_invocation
table to inspect invocationssys_inbox
table to inspect queue of pending invocationssys_keyed_service_status
table to inspect the status of a Virtual Objectsys_journal
table to inspect the invocations' journalsys_service
table to inspect the registered servicessys_deployment
table to inspect service deploymentssys_idempotency
table to inspect idempotency keysstate
table to inspect application state
You can find the schema of each of the tables in the references.
Connect with psql to Restate:
psql -h localhost -p 9071
You can change the default port 9071
by supplying the -p
argument.
To retrieve the schema of the any of the tables, connect the psql client to Restate and execute:
describe <TABLE_NAME>;
For example:
describe sys_invocation;
The Restate Introspection SQL API has been implemented based on DataFusion and supports standard SQL syntax.
Inspecting invocations
Listing ongoing invocations
- CLI
- psql
restate invocations list
select * from sys_invocation;
The sys_invocation
table only contains entries for active invocations. Active invocations are invocations that haven't completed yet and are either invoked or suspended.
Retrieving the status of an invocation
- CLI
- psql
restate invocations describe <INVOCATION_ID>
Retrieving the status of an invocation
select target_service_name, target_handler_name, status from sys_invocation where id = '<INVOCATION_ID>';
The status is either:
pending
: enqueued waiting for its turnready
: ready to be processed, but not yet runningrunning
: actively processingbacking-off
: retrying due to a failuresuspended
: waiting on some external input (e.g. request-response call, awakeable, sleep, ...)completed
: completed (this is shown only for idempotent invocations)
Inspecting the invocation journal
- CLI
- psql
restate invocations describe <INVOCATION_ID>
You see the journal printed in the output.
You can retrieve the journal of an invocation by querying the sys_journal
table:
select * from sys_journal where id = '<INVOCATION_ID>';
If you don't know the invocation id of your request, you can find it in the sys_invocation
table as described above
Inspecting invocation retries
To have a look at the invocations that are currently in a retry loop, you can execute:
- CLI
- psql
restate invocations list --status backing-off
select * from sys_invocation where retry_count > 1;
The metadata around these attempts is not committed durably to storage, but is held in memory in the invoker component.
This metadata can be found in the sys_invocation
table.
Listing invocations that are blocking a Virtual Object
You can retrieve the invocation ID that is currently blocking a Virtual Object via:
- CLI
- psql
restate invocations list --service <SERVICE> --key <KEY>
Or list all invocations that are blocking any Virtual Object:
restate invocations list --virtual-objects-only
select invocation_id from sys_keyed_service_status where service_name = 'test.MyServiceName' and service_key = 'myKey';
You can then use the invocation ID to kill the invocation.
Checking the last time an invocation was modified
- CLI
- psql
restate invocations describe <INVOCATION_ID>
Check the Modified at
field in the invocation information in the output.
select modified_at from sys_invocation where id = '<INVOCATION_ID>';
This includes any modification to the row in the table (e.g. when the service last switched its status from invoked
to suspended
, or when the last journal entry was added).
Checking how an invocation was triggered
To find out if an invocation was triggered via the ingress or by another service:
- CLI
- psql
restate invocations describe <INVOCATION_ID>
You can check this at the root of the tree in the invocation progress.
select invoked_by, invoked_by_service_name, invoked_by_id from sys_invocation where id = '<INVOCATION_ID>';
The invoked_by
field contains either ingress
or service
. If the invocation was triggered by another service, then the fields invoked_by_service_name
and invoked_by_id
will supply more information about the invoking service.
Retrieving the trace ID of an invocation
- CLI
- psql
restate invocations describe <INVOCATION_ID>
select trace_id from sys_invocation where id = '<INVOCATION_ID>';
Afterwards, you can use this trace ID to search for spans in Jaeger.
Listing inactive invocations
- CLI
- psql
To list the oldest invocations that are not making progress:
restate invocations list --oldest-first --status pending,backing-off,suspended
To retrieve all invocations that have not seen any activity for more than 1 hour:
select * from sys_invocation where to_timestamp(modified_at) <= now() - interval '1' hour;
Listing zombie invocations
Zombie invocations are invocations that are pinned to a specific deployment but that deployment was forcefully removed. You can list them by executing:
- CLI
- psql
restate invocations list --zombie
This is not possible via only psql
.
If you know the ID of the deployment that got forcefully removed, you can check if there are zombie invocations pinned to it via:
select * from sys_invocation where pinned_deployment_id = '<DEPLOYMENT_ID>';
Inspecting application state
To retrieve the state of a specific service and service key, do:
- CLI
- psql
restate kv get <SERVICE_NAME> <SERVICE_KEY>
Output
🤖 State:―――――――――service counterkey bobKEY VALseen 8
If the values are not JSON-encoded UTF-8 strings, then it is also possible to use the --binary
flag,
and get the value as base64 encoded string.
You can query the application state via the state
table.
select * from state where service_name = 'test.MyServiceName' and service_key = 'myKey';
If your state value is a regular string, then you can access its content in the column value_utf8
.
To retrieve the state of a specific service name, service key and state key, do:
select * from state where service_name = 'MyServiceName' and service_key = 'myKey' and key = 'myStateKey';
The state key is the name you used to store the state with the SDK. For example, the code snippet ctx.set("count", 1)
stores 1
under the key count
.
To join the sys_invocation
and state
table:
select * from sys_invocation JOIN state on sys_invocation.target_service_name = state.service_name and sys_invocation.target_service_key = state.service_key;
To edit application state
- CLI
To edit the application state, do:
restate kv edit <SERVICE_NAME> <SERVICE_KEY>
This command opens your default editor (as configured in the cli env
).
It sends the new state values back to the runtime to be applied.
Use --binary
if the values are not JSON-encoded UTF-8 strings.
In this case, you need to decode the base64-encoded string, and encode it back to base64 after editing.
Use --plain
to retrieve the state as a JSON object.
This can be useful in combination with tools like jq
for example:
restate kv get counter bob --plain | jq '.seen'
If during the editing of the state with the CLI, an invocation changed the state as well, then the edit of the CLI will not take affect.
If you want the CLI state edit to be applied even if the state has changed in the meantime, then use the --force
flag.
An example on how to edit the K/V state of the service counter
for the key bob
:
restate kv edit counter bob
Output
ℹ️ About to write the following state :―――――――――――――――――――――――――――――――――――――――service counterkey bobforce? falsebinary? falseKEY VALseen 8✔ Are you sure? · yesEnqueued successfully for processing