rcthomas / jupyterhub-announcement

Announcement service for JupyterHub with a UI
Other
22 stars 11 forks source link

Example of how to add announcement to Jupyter (traditional or lab)? #6

Closed milutz closed 2 years ago

milutz commented 4 years ago

@rcthomas Thanks for this great project! It's a big help to me!

Do you any examples of how to add the announcement to Jupyter itself? (I haven't dug enough to tell if the templating system is the same)

I'm using a oauth login which is so frictionless that if I don't add the message to Jupyter, my users are unlikely to see it.

rcthomas commented 4 years ago

Thanks for the feedback! I've wondered the same thing for similar reasons. Some people seem to live their entire life in a Jupyter notebook and only see the hub very infrequently.

I envision a JupyterLab extension or similar notebook UI widget that could send a request every few minutes to an arbitrary URL and convert the response into a little message displayed for the user. An extension to the status bar, something like nbresuse might be a model for that.

@krinsman what do you think, would that be a good place to put this kind of capability?

krinsman commented 4 years ago

@rcthomas I agree, that sounds like a good idea!

The lack of frictionless interoperability/information-sharing by default between JupyterHub and Jupyter Notebook is a general problem.

To the best of my knowledge, the only way a Jupyter Notebook server can distinguish whether it was launched "by itself"/standalone versus whether it was launched by JupyterHub is by determining whether or not the corresponding server uses a subclass of SingleUserNotebookApp.

So it seems like a general level, what we would want is this: if the server is using a subclass of SingleUserNotebookApp (i.e. Jupyter launched by a Hub), then the server should be pinging/asking for extra information, in this case for announcements.

I guess a way to implement a general solution to that might be to make a PR against JupyterHub which could add extra attributes to SingleUserNotebookApp to encode the information necessary to apprise the notebook server about whether it was launched by a hub or not. And then a PR against notebook (maybe, or maybe this could be contained within the PR against JupyterHub) implementing the extra backend behavior which we want to have when the notebook senses it has been spawned by a hub. Of course then there would need to be a lab extension or a PR against JupyterLab to implement the UI/frontend rendering of this extra information.

The comparison @rcthomas which you make with nbresuse is very apt. In both cases we want the notebook server to be aware of extra state/information it should have, to query some external source (psutil or another metrics program in the case of nbresuse, JupyterHub in the case of announcements) for the most up-to-date values of that information, and then we want the server to do some things with that information, but are ultimately fairly agnostic about how that information is rendered in the UI.

Moreover, the information in both cases amounts to essentially text strings (e.g. as opposed to something complicated, like a GeoJSON) which just need to be rendered somewhere.

It is relatively straightforward, but cumbersome, tedious, and laborious, to create ad hoc solutions for these every single time. I.e. create a notebook server extension to make the notebook server aware of the extra state, ping the external source for the necessary information, and possibly do some minor things with that information, and then, depending on whether one wants to cater more to classic notebook users or JupyterLab users, create an NBExtension or a JupyterLab extension which essentially just renders that extra information in a straightforward way.

To make this more frictionless, it seems like it could be a good idea to create a configurable server extension, along the lines of what Yuvi had been mentioning, which unconfigured is basically completely agnostic about what extra information the notebook server should know about, and where it should get it from. Then the user could just specify:

And then some agnostic JupyterLab widget (which could be implemented as JupyterLab extension initially) which basically just looks at all of the extra pieces of information as specified by the server extension, and then for each individual piece of information renders a line containing that information, kind of like the notifications pane on a website or an email inbox, except that the "notifications" don't have to be static, their contents would change as the notebook server updates the information presented to the UI,, without the total number of "notifications" changing.

If we could find enough use cases that could be encompassed by that single framework, we could then probably get the Jupyter team to merge them into the Jupyter notebook and JupyterLab masters, so that they wouldn't be "extensions" anymore, just built-in interfaces for making the notebook server aware of, and then display, additional information which the Jupyter developers might not have thought of.

I guess the two main challenges would be:

  1. How to create the API for the server extension such that adding new endpoints/extra state to be tracked, via configuration files or whatnot, remains simpler than just writing an entirely new notebook server extension from scratch? In particular, what assumptions need to be made about the particulars of how those things will work, which are in common to both e.g. NBresuse and JupyterHub announcements?
  2. What sort of UI representation would be good enough for all of those use cases that we could be completely agnostic about the appearance/formatting? E.g. right now actually the JupyterLab extension and NBextensions for NBResuse make some of the decisions about how the information reported by NBResuse is rendered in the UI -- if this were to be generalized, it seems like control over that would have to be delegated to the notebook server entirely, i.e. the backend part would probably have to spit out the text string we want verbatim, with the Lab part allowed no interference (since any interference would be ad hoc and therefore not generalizable). So would it just be essentially a blank space, with bounding boxes formed around text strings sent by the notebook server? That sounds like it would work, but again it would require being fairly dictatorial and making arbitrary decisions which apply to everyone using that interface (e.g. like an Apple product or black).

TL;DR: I think that a project which is sufficiently general to encompass both NBResuse and JupyterHub announcements would be very worthwhile and save a lot of time in the long-term, and could lead to features worthy of being merged into notebook and JupyterLab master, but which could probably also operate as extensions. It would also seem to require a lot of time spent up front brainstorming the ideal abstractions and architecture for such a solution.

krinsman commented 4 years ago

I guess as a short term solution, it might make sense going forward to create a notebook server + lab extension implementing this for JupyterHub announcements.

Then the next step would be to compare that with NBResuse. Such a comparison of two concrete, already implemented examples, might make it easier to identify the correct abstractions and assumptions to use.

I imagine that identifying the correct abstractions and assumptions could be sufficiently time-consuming without a second already-implemented example that writing a second fully concrete/implemented special case and then trying to generalize could be faster.

Either way such work (on brainstorming/identifying correct abstractions and assumptions) would probably require extensive conversations with the core Jupyter developers to be successful, to make sure that enough of their input is included that the end product feels like something which should be considered part of the core Jupyter ecosystem to them.

rcthomas commented 2 years ago

We've had this out for a while and have it deployed and it seems to work for JupyterLab:

https://github.com/NERSC/nersc-refresh-announcements