Repository: dask/distributed

Issue:
Use bokeh tabs on the dashboard status page?
Thanks to @ncclementi, today I learned [bokeh has a tab pane](https://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html#tabs) which allows you to switch between multiple plots in selectable tabs (see the "circle" and "line" tabs in the screenshot below).

![Screen Shot 2021-06-25 at 1 52 14 PM](https://user-images.githubusercontent.com/11656932/123472275-95e03980-d5bc-11eb-92f7-13524e97933a.png)

In our current dashboard status page, we display the number of processing tasks per worker in the lower lefthand corner. However, we have are other similar bar charts which also describe the current "load" on each worker (e.g. cpu per worker, occupancy per worker, etc). Would folks be interested in using bokeh tabs for the lower lefthand plot to allow users to switch between different "X per worker" bar chats? 

<img width="1552" alt="Screen Shot 2021-06-25 at 1 51 47 PM" src="https://user-images.githubusercontent.com/11656932/123472233-85c85a00-d5bc-11eb-9ffb-3c1d5b64b3c1.png">



Discussion:
I actually thought about proposing to ditch the tasks processing in favour of occupancy but the tabs would probably be a perfect compromise
Tabs are neat.  I don't currently feel a strong urge to use them.  If they don't clutter things and serve a purpose then great.  I wouldn't want us to spend time just because we wanted to try out a new thing though. 

Also, if people want to see what tabs feel like, the performance_report is built with tabs.
Easily switching between the nprocessing, CPU, and occupancy load plot on the dashboard landing page would, I think, be a net gain. Though I agree it's not worth spending a lot of time on right now. My hope is that someone with bokeh skills like @ncclementi could probably handle this in an hour or so (@ncclementi feel free to push back on that estimate if you think I'm being too optimistic). If that's the case, then I think it would be worth it

Resolving patch:
diff --git a/distributed/dashboard/components/scheduler.py b/distributed/dashboard/components/scheduler.py
--- a/distributed/dashboard/components/scheduler.py
+++ b/distributed/dashboard/components/scheduler.py
@@ -2808,22 +2808,40 @@ def status_doc(scheduler, extra, doc):
         if len(scheduler.workers) < 50:
             workers_memory = WorkersMemory(scheduler, sizing_mode="stretch_both")
             processing = CurrentLoad(scheduler, sizing_mode="stretch_both")
+
             processing_root = processing.processing_figure
-            processing_root.y_range = workers_memory.root.y_range
         else:
             workers_memory = WorkersMemoryHistogram(
                 scheduler, sizing_mode="stretch_both"
             )
             processing = ProcessingHistogram(scheduler, sizing_mode="stretch_both")
+
             processing_root = processing.root
-            row(workers_memory.root, processing.root, sizing_mode="stretch_both")
+
+        current_load = CurrentLoad(scheduler, sizing_mode="stretch_both")
+        occupancy = Occupancy(scheduler, sizing_mode="stretch_both")
+
+        cpu_root = current_load.cpu_figure
+        occupancy_root = occupancy.root
 
         workers_memory.update()
         processing.update()
+        current_load.update()
+        occupancy.update()
+
         add_periodic_callback(doc, workers_memory, 100)
         add_periodic_callback(doc, processing, 100)
+        add_periodic_callback(doc, current_load, 100)
+        add_periodic_callback(doc, occupancy, 100)
+
         doc.add_root(workers_memory.root)
-        doc.add_root(processing_root)
+
+        tab1 = Panel(child=processing_root, title="Processing")
+        tab2 = Panel(child=cpu_root, title="CPU")
+        tab3 = Panel(child=occupancy_root, title="Occupancy")
+
+        proc_tabs = Tabs(tabs=[tab1, tab2, tab3], name="processing_tabs")
+        doc.add_root(proc_tabs)
 
         task_stream = TaskStream(
             scheduler,


Test patch: