Save a gateway view and share it
Keep a question you asked of a gateway's traffic, share it with your team, and understand why two people see different answers.
On this page
You spent ten minutes narrowing a window, a set of applications and five metrics until the number on screen answered the question somebody asked you in a meeting. Tomorrow you want that question back, and so does the colleague who asked it.
A saved view is that question, kept under a name. It stores no query language and no permission: opening one asks the stored question again, on behalf of whoever opened it. Two people on the same view can therefore see two different answers, and both are correct.
You need an organization id (org_…), a workspace id (t_…), and metadata.read on
the scope the question asks about. Saving a view for your team additionally needs
metadata.read for every explicitly selected application and gateway. An unfiltered
workspace question requires workspace access; a mixed question is refused if any
selected application is outside the viewer’s authority. Money metrics inside the question still need
cost.read at the moment somebody opens it.
Read your gateway’s traffic and spend covers asking the
question in the first place, and this page assumes you can already ask it.
Every command block on this page is program output, captured by replaying the recorded
lane answers in sdk/spec/insight-read-fixtures.json through a loopback server, so
--base-url names 127.0.0.1 and a port that changes on every run. Yours names your
deployment.
What a view stores, and what it cannot store
A stored view holds the question document, a name, an audience, how it is dated, and a display zone. It holds no rows, no answer and no access.
| Field | What it holds |
|---|---|
name |
the words you would use to ask for it out loud |
audience |
personal (only you see it) or team (everyone in the workspace sees the question) |
query |
an insight-query/v1 document: scope, window, purposes, metrics |
time_intent |
relative with a span, or fixed with the window it was saved at |
display_tz |
the IANA zone every reader sees the times in |
revision |
a forward-only counter, carried as a decimal string |
Five members are turned away by name if they appear anywhere in the question document:
sql, raw_sql, grant, grants and role. A view is a question, so there is no
member of one that could carry a statement or a permission, and both the server and the
CLI say which member was found.
List and open the views you can see
view list answers with the views you can see: your own, plus the team views your
current access still reaches. It does not say how many exist in the workspace, because
that read cannot support such a claim.
$ tokentriage cloud view list --org org_K11111111111 \
--workspace t_K11111111111 --base-url http://127.0.0.1:2503
sview_K11111111111 Checkout spend, last 24h team fixed overview revision 1
sview_M11111111111 A question this build lost team fixed overview revision 1
view get prints the stored row and says, on stderr, that a row is not an answer:
cloud: this is the stored QUESTION and not its answer; `cloud view open` answers it under your own scope
view open returns the question and the answer in one document, so a chart and the
caption above it cannot come from two different moments of your access:
$ tokentriage cloud view open --org org_K11111111111 \
--view sview_K11111111111 --base-url http://127.0.0.1:2507
sview_K11111111111 Checkout spend, last 24h team fixed overview revision 1
application requests.v1 1284 count
application provider_spend.v1 unavailable (unpriced_population)
application cost_per_1000_requests.v1 unavailable (unpriced_population)
application tokens.v1 84210773 tokens (FLOOR: ingest_gap:gateway_journal)
application response_latency.v1 412 milliseconds
Two of those cells carry no figure, and one is a floor. Read your gateway’s traffic and spend covers how to read each state; opening a view changes none of it.
Save the question that is on screen
The portal is where a question on a screen becomes a view, because the portal is the surface that has one. Open a gateway, set the window, the activity purposes and the metrics you want, and save from there. The panel writes the question the screen is asking; it offers no second editor for the query document, so a saved view cannot disagree with the screen it was saved from.
Four fields decide what you get:
- What this view answers. The name, up to 200 characters.
- Who can see this question. “Only me”, or “Everyone in this workspace”.
- How this view is dated. “A rolling window”, re-dated on every open, or “The exact window on screen”, frozen as it is now. Rolling spans are a choice of last hour, last 24 hours, last 7 days or last 30 days rather than a free number, because a span the producer turns away is a failure nobody can act on.
- Show times in. An IANA zone name, applied for everyone who opens the view, so a shared view does not read as a different day to different people.
The saved-view page of one gateway lives at
/account/orgs/{org}/applications/{app}/gateways/{gw}/views/{sv}, and carries the
workspace in the ?workspace= search parameter like every other portal address. That
URL is the thing a colleague pastes into chat. It lists, opens, edits and deletes; it
does not create, because creating needs the question from the screen that asks it.
Save the same question from a file
The CLI draws no chart, so there is nothing on it to “save the current view” from. It
takes the question as an insight-query/v1 document, which is the same document
cloud insight overview --json prints. Keep it in a file and store it under a name:
$ tokentriage cloud view save --org org_K11111111111 \
--workspace t_K11111111111 --name "Checkout spend, rolling 24h" \
--query-file question.json --time-intent relative \
--relative-window 24h --base-url http://127.0.0.1:2509
sview_W11111111111 Checkout spend, rolling 24h personal relative overview revision 1
The audience defaults to personal and the new row starts at revision 1. The body that
went out carries the question, the intent and the window in nanoseconds. It carries no
owner, because there is no owner member to put anybody’s name in: the creator’s scope is
stamped from their own resolved authority.
Both packaged SDKs carry the same six operations under saved_views (Python) and
savedViews (TypeScript): list, get, create, update, delete and open.
Edit at the revision you read
An edit replaces the whole view and names the revision the editor saw. Over a document with a scope inside it, “did not mention the scope” and “cleared the scope” would be the same bytes, so every member travels on every edit:
$ tokentriage cloud view edit --org org_K11111111111 \
--view sview_W11111111111 --name "Checkout spend, shared with the team" \
--audience team --query-file question.json --time-intent relative \
--relative-window 24h --expected-revision 1 \
--base-url http://127.0.0.1:2511
sview_W11111111111 Checkout spend, shared with the team team relative overview revision 2
Send the same bytes again and the row does not move. The second editor in a race gets a 412 that names the revision the row is at now:
customer.saved_views.update was refused as a stale revision (HTTP 412): re-read the resource and retry with its current --expected-revision; detail: foundation: stale revision: saved view sview_W11111111111 is at revision 2 and the edit expected 1; type=precondition_failed; request_id=req_saved_view_update_stale_revision
The remedy is to read the row again, re-apply your change and send that. Retrying these bytes with a bumped revision would overwrite an edit nobody would have seen losing. The portal says the same thing in words and offers one button, “Read this view again”; it offers no retry.
In the portal, a question that has drifted from the view it was opened from shows an “Unsaved changes” chip and a sentence naming what “Update” would replace. A rolling view does not sit permanently in that state: drift is compared on the stored span, not on the window an open happened to be re-dated to.
What goes wrong, and which person fixes it
| What you see | What happened | What to do |
|---|---|---|
HTTP 422, validation_failed naming a member |
the question document carried sql, raw_sql, grant, grants or role |
remove the member; nothing was saved |
HTTP 422 on open while get still works |
the stored question names something this build no longer publishes | edit the question |
HTTP 412, precondition_failed |
somebody edited the view after you read it | re-read, re-apply, send again |
HTTP 409, conflict |
a ceiling: 50 views per owner in a workspace, or 500 per workspace | delete a view you no longer open |
HTTP 403 on delete |
you can see this team view but do not own it and do not run the workspace | ask the owner or a workspace administrator |
HTTP 404 on delete |
the view is not one you can see at all | check the id and the workspace |
The 422-on-open pair is the one that surprises people. The row reads perfectly and you are allowed to read it; what the build cannot do is ask the question again:
customer.saved_views.open was refused (HTTP 422); detail: foundation: unsupported combination: saved view sview_M11111111111 asks a question this build cannot re-ask: insightcontract: metric version unknown; type=validation_failed; request_id=req_saved_view_open_stale_question
It is not a 404 and not a 403, so nobody needs to be asked for anything. The portal prints the server’s own sentence and adds one line: the remedy is to edit the stored question.
Why 403 and 404 differ on delete
Somebody who can see a team view but may not remove it is told they may not; somebody who cannot see it at all is told there is no such view. Answering the other way round would turn a delete into an oracle for which questions colleagues keep.
When two people see different numbers
A team view is re-resolved per reader on every open, so a colleague whose access reaches fewer applications than yours gets a narrower answer to the identical question. The portal shows the rows it did get and a banner above them saying which part of the question this reader was not answered for, in one of two shapes:
- the stored question named applications, gateways or environments the reader is not answered for, which the panel can state as a fact because it holds both lists;
- the stored question named none on that dimension, meaning “every descendant I may read”, and the answer came back with an explicit list. The panel says the resolved count may be fewer than somebody else sees, and claims nothing more.
Blanking the panel instead would tell that reader their traffic was empty, which is a claim about their application rather than about their access.
What a saved view does not do
It grants nothing, and deleting one removes a question and no measurement. It stores no
chart: the portal decides how an answer is drawn, and the stored document names only
metrics, a window, purposes and a scope. It carries no schedule and mails nobody. And an
open never widens a reader’s scope to the author’s, which is the whole reason the same
view can answer two people differently.