Slicing dashboards

Slicing is a mechanism to compute many variants of the same dashboard and let end-users interact with the resulting sliced dashboard through a search-like navigation. For example, through slicing, it is possible to create a product inspector which consolidates - for every product - all the KPIs and linecharts of interest.

The following script provides a simplistic variant of such a dashboard:

table Products[Pid] = with
 [| as Product, as Color, as Price |]
 [| "pants", "blue", 25 |]
 [| "shirt", "white", 15 |]
 [| "socks", "green", 5|]

Products.Slice = sliceDashboard(Products.Product) by Pid

show table "My Products" a1c3 slices: Slice with
  Products.Product
  Products.Color
  Products.Price

In the above script, the function sliceDashboard() takes one argument Product.Product and one option Pid. The argument is the name of the slice. Slice names become part of the dashboard user interface, as the slice selector offers the possibility to select slices displayed through their names. The option is the group of the slice, in a process highly similar to the group tables detailed in a previous section. Finally, the table tile gets sliced through the tile option slices: Slice. Note that we are referencing Slice instead of Products.Slice. The latter would have been acceptable as well, however as Slice is a dimension, it does not actually need to be prefixed - except the first time, when calling sliceDashboard().

Slicing is a mechanism that impacts only tiles and only when specified at the tile level. When a tile is sliced, its input table (found as the common table among all its input vectors) gets partitioned across every single slice. The resulting tile is computed separately for each slice. Finally, the slice selector allows you to pick which slice gets displayed in the dashboard itself.

The function sliceDashboard() can be called at most once in an Envision script.

The option by behaves like it does for any aggregator, the only limitation being that the number of slices is limited to 200,000. In particular, it is possible to use multiple vectors through the usual syntax by [expr1, expr2, expr3].

It is recommended to have the return variable named Slice. No matter how the returned dimension is named after the call to sliceDashboard() a table named Slices, which has Slice as a dimension, becomes accessible.

Roadmap: The variable returned by sliceDashboard() is a dimension, associated to the implicitly named Slices table. A syntax like table Slices[Slice] = sliceDashboard(foo) by bar, which clarifies both the nature of Slice (a dimension) and its associated table (Slices), would be better and will most likely be introduced in the future. The guideline concerning the Slice name will make the future automated code rewrite less impacting.

The function sliceDashboard() accepts a second argument to specify a label (the first argument is the name, see above). The label can be used to enrich the slice selector as illustrated by:

table Products = with
 [| as Product, as Color, as Price |]
 [| "pants", "blue", 25 |]
 [| "shirt", "pink", 15 |]
 [| "shirt", "white", 15 |]
 [| "socks", "green", 5|]

Products.Slice = sliceDashboard(\
  Products.Product,\
  join(Products.Color; ", ") by Products.Product sort Products.Color)
  by Products.Product

show table "My Products" a1c3 slices: Slice with
  Products.Product
  Products.Color
  Products.Price

In the script above, the second argument join(Products.Color; ", ") .. is the concatenation of the color values. Indeed, unlike the previous example, the shirt slice has two elements instead of one as we are grouping by Products.Product (while we were previously leveraging the autogenerated dimension Pid of the Products table).

The option by Products.Products is required in the script above, but this requirement is somewhat accidental. As the table Products appears on the left side of the assignment, into Products is added by default to any aggregation that does not specify its by on the right. However, in this case, the target table for the text concatenation is not the Products table by the Slices table itself. This quirk would also be eliminated by the future syntax (cf. roadmap above).

Advanced remarks: Envision, and its implementation by Lokad, is geared toward batch processing where scripts are run fast, from minutes (for the big ones) down to a few seconds (for the small ones). Once the execution of a script is complete, our goal is to maintain a latency under 500ms to display even very large dashboards over typical internet connections. However, our goal is not to run a script (even a small one) in milliseconds. Indeed, guaranteeing low latencies while supporting a language having the level of expressiveness of Envision is a devilishly difficult problem. The slicing mechanism can be seen as a way to cheat with latencies. Instead of being able to compute a small dashboard very fast (while enforcing plenty of restrictions on the computations themselves), Lokad precomputes up to a large number of dashboards (with no particular restrictions on the computations), and then serves the pre-computed results very fast. Under the hood, each slice remains stored on the server-side and only gets pushed to the client browser when the slice is effectively visited.