Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add server status endpoint #81

Merged
merged 3 commits into from
Oct 30, 2019

Conversation

bollwyvl
Copy link
Collaborator

For https://github.com/krassowski/jupyterlab-lsp/pull/78#issuecomment-546907659

This adds a REST-ish (whatever) JSON endpoint for getting the current state of the server sessions at /lsp (no trailing slash).

example response
{
  "version": 0,
  "sessions": [
    {
      "languages": [
        "bash",
        "sh"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "css",
        "less",
        "scss"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "dockerfile"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "html"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "javascript",
        "jsx",
        "typescript",
        "typescript-jsx"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "json"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "markdown",
        "ipythongfm"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "python"
      ],
      "handler_count": 1,
      "status": "started",
      "last_server_message_at": "2019-10-30T04:30:53.069124+00:00",
      "last_handler_message_at": "2019-10-30T04:30:52.219183+00:00"
    },
    {
      "languages": [
        "r"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    },
    {
      "languages": [
        "yaml"
      ],
      "handler_count": 0,
      "status": "not_started",
      "last_server_message_at": null,
      "last_handler_message_at": null
    }
  ]
}

Not sure what else we're looking for at this point.

There is a JSON schema (for testing, not presently hot validating) which we could generate typescript with, if that helps.

Everything it reports is already evented through traitlets, so this could relatively easily be Yet Another WebSocket, but we'll cross that bridge when we have to, I suppose, as it would require a breaking change to the URL schema, probably. Perhaps lsp/server/python and lsp/servers or something.

It also currently doesn't detect error states in a meaningful way, but we could potentially infer them by looking at the queue lengths, perhaps.

@jupyterlab-dev-mode
Copy link

Thanks for making a pull request to JupyterLab!

To try out this branch on binder, follow this link: Binder

@krassowski
Copy link
Member

Can we get a list of all auo-detected + manually configured language servers, e.g. under "available_servers"?

@krassowski
Copy link
Member

krassowski commented Oct 30, 2019

Also, I'm not sure how to identify the sessions on the frontend. Can we intercept the filename and use it as an identifier?

@bollwyvl
Copy link
Collaborator Author

Yeah, so this is revealing a few things deeper in the model that I haven't really documented (which this will further complicate). I should probably draw a picture of it. Any qualms about going "full lab" and using jupyterlab-drawio?

get a list of all auo-detected + manually configured language servers

this is all the detected (potential) servers

  • they only thing you're not getting is argv, which won't be super helpful to the user
  • a display name would be good, but some of them are "cute", or just confusing, but frankly, mostly people care about the language
  • there is only one session per language server, as there's only one process per language server

Also, I'm not sure how to identify the sessions on the frontend.

there isn't much to identify. Each websocket (handler_count) gets all of the messages from all of the like-languaged servers it can talk to

  • there should probably only ever be zero or one websocket per language server
    • exactly one initialze request should be made
    • the request ids should probably be unique across the whole system
    • everything else should probably be managed on the client, based on the request ids (when appropriate)
    • some things (like diagnostics) don't even have a request id, because they just are... hence the uri check

Can we intercept the filename and use it as an identifier?

  • we don't do any message inspection (much less parsing!)
    • i want to add that feature, once we have the first compelling use case for it (this might be it)
    • so the hook would look something like
def load_jupyter_server_extension(nbapp):
    # obviously we wouldn't do it this way, but what would someone else do?

    # another extension developer might need to IOLoop.call_later
    mgr = nbapp.language_server_manager

    @mgr.on_message(languages=".*", methods=r"textDocument/did(Open|Close)")
    def do_thing_with_message(
        # would be nice if i could generate this from a JSON schema
        message: LSPMessage, 
        # it would be nice if these had common read/write API 
        sender: Union[LanguageServerSession, LanguageServerWebSocketHandler]
    ):
        open_file_uris = list(mgr.open_file_uris)

        try:
            method = message["method"]
            uri = message["textDocument"]["uri"]
        except:
            return

        if method == "textDocument/didOpen" and url not in open_file_uris:
            open_file_uris.append(uri)
        elif method == "textDocument/didClose" and url in open_file_uris:
            open_file_uris.remove(uri)
        else:
            return

        mgr.open_file_uris = open_file_uris
        # ...and then it would go off an do something on the reporting channel

@krassowski
Copy link
Member

Okay, I get it now, I misread the example. I though that sessions correpond to connections, but they reallly correspond to language servers (and those are actually sessions for the backend). Sorry about that!

@bollwyvl
Copy link
Collaborator Author

bollwyvl commented Oct 30, 2019 via email

@krassowski
Copy link
Member

krassowski commented Oct 30, 2019

Now I see that you got this covered in schema ("a list of servers that are, could be, or were running"), so that is fine no need to rename.

However, I think that it would be useful for the users to know the name of the language server (and to have it here so we can expose it in the UI). For example, is the pyls running or Microsoft's python-language-server? This is of course not so important yet, but once other power-users will start playing around with settings and swapping the LSP servers to their liking this could become an annoyance.

Even better, we could require (or allow) an additional filed in our python-based LSP specification with the URL to the repo or documentation of the server - this way we could hint the users (directly in the UI) where to go to discover server-specific configuration.

@bollwyvl
Copy link
Collaborator Author

bollwyvl commented Oct 30, 2019 via email

@bollwyvl
Copy link
Collaborator Author

bollwyvl commented Oct 30, 2019 via email

@krassowski
Copy link
Member

Sounds good. Btw, jupyterlab-drawio requires some attention, I use it daily but there are some annoying bugs I wish I had time to fix.

@krassowski krassowski merged commit 99da868 into jupyter-lsp:master Oct 30, 2019
@krassowski
Copy link
Member

Thank you! I will use it for the status bar tonight!

@bollwyvl
Copy link
Collaborator Author

bollwyvl commented Oct 30, 2019 via email

@@ -0,0 +1,68 @@
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am experimenting with augmenting the statusbar with the server extension status; I was thinking about generating typescript interfaces from this schema e.g. with https://www.npmjs.com/package/json-schema-to-typescript. Any experiences or thoughts on this @bollwyvl?

@bollwyvl
Copy link
Collaborator Author

bollwyvl commented Nov 5, 2019 via email

@bollwyvl
Copy link
Collaborator Author

bollwyvl commented Nov 5, 2019

#90 is ready for review: if you like, I can take a crack at generating some types into a new package, or you can go after it closer to the work where you want it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants