Metrics Notebook
Metrics Notebook keeps a list of saved, named metric queries and shows the result
of running one as a table. It ships no dedicated host page, renderer component
or app-specific runtime branch. Its source is apps/metrics-notebook/app.toml;
the native records are in
crates/shared/schema/app-metrics-notebook/src/lib.rs.
Supported workflow
The notebook starts empty. New query opens a dialog that takes a name, a target metric and an optional description. Each saved query has two run buttons:
- Run summary groups the matching samples by service and shows the count, average, minimum and maximum.
- Latest samples shows the 50 most recent matching samples.
Edit opens the query page. There you can change the name, metric and description, or delete the query.
Queries read the app's own MetricSample dataset. The Record a sample form
on the notebook page appends a sample (metric, service and value), and the
server sets its timestamp. This keeps the app self-contained, so it needs no
cross-app dataset grant.
One package, existing host
| Package declaration | Shared implementation |
|---|---|
Native MetricQuery and MetricSample schemas | Descriptor validation, typed CBOR records and per-field merge |
metric-query-list pipeline | Authorized dataset read, filters, deterministic sort and projection |
metric-summary and metric-recent pipelines | The invoke_pipeline action with one signed input binding, applied as an overlay filter |
| Create, edit and delete actions | Durable entity operations, optimistic projection and explicit field masks |
Bound table views | The shared data-view host |
foreground_snapshot_v1 | The installed host's bounded foreground refresh scheduler |
The release requests read and write access to
app.metrics_notebook.MetricQuery and app.metrics_notebook.MetricSample, and
invocation of the three pipelines. It requests no network, secret, notification
or infrastructure capability.
Author, build and install
rac app validate apps/metrics-notebook/app.toml
rac app build apps/metrics-notebook/app.toml
rac des spec publish --manifest apps/metrics-notebook/pipelines/metric-query-list.toml
rac des spec publish --manifest apps/metrics-notebook/pipelines/metric-summary.toml
rac des spec publish --manifest apps/metrics-notebook/pipelines/metric-recent.toml
rac app publish apps/metrics-notebook/app.toml
rac app install metrics-notebook --version 0.1.0 \
--installation-id metrics-notebook-example \
--grant notebook-read,notebook-write,notebook-pipelines
Publication requires the same registry authority and grant review described in
the release lifecycle. Only
build/app-release.json is checked in.
Bounds
The query list returns at most 200 live queries, sorted by name. The summary
reads at most 200 grouped rows and the recent view returns 50 rows. The only
user-chosen part of a query is the metric it filters on. The grouping
(metric, service), the aggregates and the row limits are fixed when the
pipelines are signed.
Friction log
These are the problems we hit while building the app. We describe them here without filing tickets.
- No delete operation. Entity operations are only create, set_fields,
add_set_element and remove_set_element. Delete is a soft delete: a
deletedbool written through adeletedfield mask, which the list pipeline filters out. Deleted records stay in storage. - One parameter per pipeline invocation.
invoke_pipelinebinds a single input value, and its column, operator and value kind are fixed at signing. Users therefore cannot choose a column, operator, aggregate or limit. The "query" is a saved filter value plus a choice between two pre-signed shapes. - The overlay filter runs after the base stages. The parameter filter is
appended after the pipeline's own stages. The summary fold must therefore keep
metricingroup_by, or the filter column would no longer exist. We have not verified whether the 200-row source limit applies before or after the fold. - Table columns are static. A
tableview descriptor is a literal string, so the two result shapes need two tables, chosen withv-ifflags. - Collections need a fixed group. Optimistic and hydration config requires
a group, so the list is
v-for group in $state.queriesaround alist. There are no index paths such asqueries[0].items. v-iftakes only booleans and lacksv-else-if. We set the derived flags (show_summary,show_recent,sample_recorded) with literal action steps. The "no result yet" state is a nested negatedv-if.- Prop enums are checked only at validate time.
variant="ghost"andtone="success"passed authoring and failedrac app validate. A texttonealso propagates onto inline children. - Async table in host tests. The
tablenode renders through the asyncDataViewHost. The host test therefore checks the compiled rows binding rather than rendered cells. - Observation:
remoteInstalledRuntimeAppSource.tsstill containsmedia-specific branches in shared host code.