This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-30
Channels
- # announcements (1)
- # babashka (15)
- # calva (3)
- # cider (1)
- # clj-kondo (16)
- # clj-on-windows (1)
- # cljfx (1)
- # clojure (25)
- # clojure-europe (6)
- # clojure-spec (15)
- # cursive (13)
- # emacs (11)
- # fulcro (2)
- # humbleui (7)
- # introduce-yourself (1)
- # jackdaw (1)
- # off-topic (10)
- # pathom (5)
- # portal (3)
- # re-frame (7)
- # reagent (12)
- # releases (1)
- # shadow-cljs (8)
- # tools-build (18)
- # web-security (10)
Why the sudden interest into nitty gritty details of Portal? Because I have this (crazy?) idea to use it as a production troubleshooting tool, instead of needing access to a prod REPL. Why Portal? Because it excels at displaying data, allows me to search lists of data via its filtering capability, can navigate to related data with nav
, allows me to execute functions via Commands, and has a UI accessible over HTTP. And it supports multiple concurrent users, with its concept of sessions (and I can have per-user state, if I put it inside an atom keyed by (:session-id portal.runtime/*session*)
).
Most of the time what I need for troubleshooting is to navigate data (what does the User look like? What are her Privileges? ...) and to execute a few functions and check their result/error/timing. So Portal seems to be a good fit.
Upon start I would submit
a list of all the tables, when I access its element I would via nav
list the table (a small subview, e.g. just the id and name of things) and allow you to navigate to a more complete view of the thing and run some commands on it. This enables me also to control what data you see - instead of showing all columns of a table, I can only see what is deemed acceptable by the clients so that it is sufficient for troubleshooting but does not reveal unnecessary information.
Security considerations: Portal would only be accessible on the localhost and a developer would tunnel to it via a bastion, possibly with an authentication proxy in front of it. The nav
impl. and commands could even produce an audit trail for later review.
What do you think about it? Are there some obvious problems I am missing?
I imagine I might eventually want to implement an alternative to the existing client-side filter that would allow me to specify a query (eg. in the https://walkable.gitlab.io/walkable/1.3.0/filters.html) for execution on the server side. A nice benefit is that I could search for a thing by name without Portal revealing the names of all the things to me (assuming I got the name from e.g. a bug report). I will also likely run quickly into the need for commands with arguments. The built-in ones already support some (drop-down based) and I suppose Portal could be hacked to to what I will need.
My long term plan is to enable this type of monitoring / app specific dashboards so I'm excited you are trying it out! One feature that might be useful is providing your own atom as the root value of Portal to display in the UI. If you are hitting Portal from the browser, you can use https://github.com/djblue/portal/blob/master/src/portal/api.cljc#L41-L47 to set the root value for any new sessions. For example:
(def app-state (atom {:app-logs [] :taps [] :http-logs []}))
;; app instrumentation against the above atom:
(defn submit [value]
(swap! app-state update :taps conj value))
(add-tap submit)
;; ...
(portal.api/set-defaults! {:value app-state})
This way you could quickly hit an endpoint and view any of the recorded information.Nice! Thank you!