Open Bug 885508 (network-websocket-inspector) Opened 7 years ago Updated 3 days ago

[meta] WebSocket Inspector

Categories

(DevTools :: Netmonitor, defect)

defect
Not set

Tracking

(Not tracked)

People

(Reporter: canuckistani, Unassigned)

References

(Depends on 30 open bugs, Blocks 1 open bug)

Details

(4 keywords, Whiteboard: [difficulty=hard] [DevRel:P1])

User Story

Summary: our tools should allow developers to visualize the websocket connections, this means providing transparency for the frames as defined in RFC 6455, and providing a way to correlate the frames and the events produced by the browser WS API implementation. At a high level, here are the features we need:

1) The core information that belongs in the network inspector for websocket MUST be frames, and not messages. There are several reasons for this:
- RFC 6455 specifies how websocket works, what goes over the network are frames, not what the websocket API interprets. We need to provide developers with transparency for RFC 6455.
- Putting messages into the network inspector is totally redundant and useless because the developer can already get this information via the debugger, there's really no use for it in the network inspector. You just put a break on the websocket API calls.
- If we were to put the messages in there, we are effectively instrumenting the websocket API, when instead we should be inspecting the network itself, since that is what the network inspector is meant to be. 

Obviously, the frames should be grouped by WS connection, and the WS connections should be discoverable (US 1203308). Note that in the future, websocket connections in workers will make the discovery process a little more complicated from a presentation point of view.

US 927481 covers the websocket frame inspection. There are currently six frame types that are identified by RFC 6455, plus 10 more open for future expansion. At the very least, we must provide developers with a view of the basic six frames and their associated meta-data. Only perf issue here is whether displaying data content on payload frames would cause excessive memory usage and/or excessive frame rate slow down

2) We should provide developers with the ability to BRIDGE the websocket API with the frames. This means we need to provide a way for the developer to be able to go from a websocket API event to the frames associated with that event. Perhaps the most useful example would be an error message. The network doesn't produce an error, the WS API does. And if an error takes place, we need to show the user what frame caused the error. Similarly, a ws.onmessage event should be correlated to all the associated frames. One way to do this is to overlay the API events on top of a frame timeline. As a bonus we could also make sure we can at least highlight JSON objects in the frames. Bug 1197903 outlines the need for the JSON parser.

3) Search for patterns, frames, etc...

1) 2) and 3) are part of the minimum viable product.

Then there are some interesting additional features we can provide:

4) Protocol upgrade intelligence: make the grouping UI extensible so that someone could correlate to upgraded protocol attributes. For example, show frames that represents STOMP payloads and can decode the stomp control frames.

5) We should provide developers with a means for setting BREAKPOINTS that are based on frame attributes, and not on the API itself. A developer should be able to trigger the debugger to break when a particular frame pattern is detected. So for example, break on the 4 bit Opcode, here are the different types of break possible:
      *  %x0 denotes a continuation frame
      *  %x1 denotes a text frame
      *  %x2 denotes a binary frame
      *  %x3-7 are reserved for further non-control frames
      *  %x8 denotes a connection close
      *  %x9 denotes a ping
      *  %xA denotes a pong
      *  %xB-F are reserved for further control frames



Old stuff is below this line.

-----------------------------------

It should also be possible for the community to extend the websocket monitoring framework to support specific protocol parsing so that protocols can also be monitored.

The platform work for websocket did not include any support for being able to debug and monitor websocket communications. As a result, any tooling will have to be preceded by some platform work to enable tooling.

Features at a Glance
Websocket frames
The heart of the tooling should enable developers to inspect individual websocket frames. Pretty much everything can be added on top of individual frame inspection.

Websocket state changes
http handshakes, Open, close, error and protocol upgrades are the major websocket events that should be visible in a tool.

Multiple websocket connections
Whatever tool we implement, it has to have support for multiple websocket connections. This could be achieved by providing a filter, or by having the UI display any websocket data based on each WS connection.

Protocol support
WS was designed specifically so that developers did not have to be constrained by the http protocol and instead can select the most appropriate protocol for the task they are trying to solve. For example. STOMP or AMQP are popular protocols for solving publish/subscribe type problems such as those encountered in stock market applications. SocketIO is a protocol that was loosely implemented for chat problems but is used extensively for many applications requiring basic real time messaging.

The most ubiquitous tasks for developers is to be able to inspect payloads for specific protocols. Such inspection includes both the payload itself (JSON, Binary JSON, binary) and the wrapper, such as message options and topic and subscription information, i.e. who is supposed to receive the message. The knowledge of the protocol is embedded in the protocol upgrade event, and if it's a readable protocol, our tool should be smart enough to use the right parser. Any given payload is an assembly of frames that have to be pieced together by the parser according to the protocol.

The three most popular open source protocols are SocketIO, STOMP, and AMQP, but AMQP does come in two distinct flavors, v. 0.9 and v. 1.0, both are in use and are very different. We should solicit the community to help us implement the parsers.

websocket extensions
The WS standard supports WS extensions. These allow specific vendors to add meta-data to frames so that additional functionality can be overlaid on a websocket stream independent of which protocol runs on the websocket connection. Our tools should be smart enough to decipher the content of the meta-frame data.

Attachments

(1 file, 2 obsolete files)

We should allow for some sort of inspection of websocket connections and traffic in netmonitor.

Marking this as dependent on bug 720176 and in particular the back-end work implied there.

When we get to this work though, let's circle back, discuss/(in)validate our  assumptions and agree on the requirements and an MVP. I'm hugely interested in WebSocket support and can provide a mini-prd for it.
Priority: -- → P2
Whiteboard: [reasons-i-use-chrome-dev-tools]
Whiteboard: [reasons-i-use-chrome-dev-tools]
Blocks: perf-kanban
Adding to the perf management stack which is supposed to include network inspection. This should be a user story like this: As a web or app developer using websocket, I'd like to inspect websocket frames so that I can debug my websocket connections. 
Acceptance criteria: the network monitor panel should allow me to look at the content of individual websocket frames. 
This should be for the generic websocket frames and not some protocol like socket.IO running on top of WS. We should file a couple of other user stories to cover the ability to write custom parsers that can decode specific websocket frames and actually write one example parser that handles socket.io. This is mainly so developers can easily find and look at payloads. Currently, if a protocol runs on top of WS, a payload could span multiple WS frames.
Would it make sense to provide the data sent along a web socket (not each frame, but each send/onmessage) as a v1 before we get at each individual frame? Maybe via monkey patching the same way Victor did with WebGL for his shader editor? At least that way we would be able to monitor data even if we couldn't see every single detail...
Attached patch websocket-logging.patch (obsolete) — Splinter Review
This WIP patch adds a WebSocketActor when you start listening to network events from the console. It sends events on open, close, error, message, and send.

If we think it is worth it to skip frames, and just have logs of what is being sent, it would be pretty easy to build a UI on top of this.
(In reply to Nick Fitzgerald [:fitzgen] from comment #3)
> If we think it is worth it to skip frames, and just have logs of what is
> being sent, it would be pretty easy to build a UI on top of this.

In a v1, that is. Would of course want to expose frames eventually.
Nick: \o/

Question for Axel though - is this enough or do we really need frames? So an add-on could hook on message and send events and parse the full messages with a protocol parser?
Initially I was thinking of frames but come to think of it, for most web developers, just parsing the WS API should be plenty, and is actually better than looking at the frames themselves. One thing about WS is that the message will always be "whole", i.e. not less than the buffer to make the send/receive non-blocking.

TCP chunks get re-assembled by websocket into frames and the frames make up messages. The frame level stuff is important for working with WS extension stuff, but I doubt too many web developers will be messing with that. The protocol libraries typically sit on top of the WS API in the browser, so there's really no need to look at the frames.
Victor:

Should I continue to work on this backend? Was having trouble filtering out the right window object (so its not even included in the attached patch). Or should we do something with nsIWebSocketListener instead? Not sure of the full capabilities there, or how to integrate it.

Victor/Darrin:

What should the UI in the network monitor front end look like?
Flags: needinfo?(vporof)
Flags: needinfo?(dhenein)
My vote is at least to get the back-end in so we can play with it. I know Axel has some ideas on what the suer experience for this tool should be.
hey Nick, Victor: Are either of you assigned to this?
I can take it, just need the requested info from above.
Assignee: nobody → nfitzgerald
Can I get a bit more information on the UI we are building? The only websocket debug experience I am familiar with is Chrome's which essentially gives you a table of frame(s) data for a given socket connection. Nick, can you elaborate? What are we showing the user as a 'message'? Is it a collection of frames, etc? Or should we be showing individual frames?
Flags: needinfo?(dhenein) → needinfo?(nfitzgerald)
I'm not super familiar with the websocket spec, so I don't know if frames == messages. Messages are whatever the user gets every time the |socket.onmessage| listener is called or |socket.send| is used to send data back across the websocket.

What I was imagining was a vertical log/timeline that shows who sent things which direction and when:

=======================================================
Client                                           Server
=======================================================

---------------------- Open ---------------------------

packet1 ---------------------------------------------->

<---------------------------------------------- packet2

<---------------------------------------------- packet3

<---------------------------------------------- packet4

packet5 ---------------------------------------------->

packet6 ---------------------------------------------->

---------------------- Error --------------------------

---------------------- Close --------------------------

=======================================================

Then maybe each log would be expandable into a variables view with all the JSON properties if the packet is a JSON string, or maybe just expand and show whatever we can. Timestamps might be nice too.

Wasn't thinking anything too different from chrome, but just better in general, and also maybe you can think of a better UI. Last time I used theirs, it wasn't updated live which is crappy. We can do better.
Flags: needinfo?(nfitzgerald)
(In reply to Nick Fitzgerald [:fitzgen] from comment #7)

I think experimenting more with the backend is definitely a good idea at the moment. What the UI will look like is a discussion we can and should have, but without a backend there's no way of knowing what the frontend can even show. Your mokey-patch-methods-idea sounds good to me!

If you have the time, go on and hack on this. Keep us posted on what's happening, give me a call if there's anything special I can help with!
Flags: needinfo?(vporof)
(In reply to Nick Fitzgerald [:fitzgen] from comment #7)
> Victor:
> 
> Was having trouble filtering out
> the right window object

Still need help finding the right window object to patch. Was never able to figure it out, so I just tested if the global has a WebSocket property, but obviously that is not enough.
Flags: needinfo?(vporof)
We're doing the API, not the actual frames. WebSocket messages consist of one or more frames. Messages themselves do not have any length indication built into the protocol, only frames do. But because we are using the API, we will know what the content of the message is. 

In general, web developers don't work at the frame level. Only the folks that write plumbing for websocket do. Web developers are interested in the actual payloads and in the connect, disconnect and error messages.If there is a library that encodes or decodes the webSocket traffic, it still does this based on the send and receive API. But if a protocol runs on top of websocket, then what the web developer wants to know is the actual content of the payload and getting the payload headers for the messaging protocol that they use.
(In reply to Nick Fitzgerald [:fitzgen] from comment #14)
> (In reply to Nick Fitzgerald [:fitzgen] from comment #7)
> Still need help finding the right window object to patch. Was never able to
> figure it out, so I just tested if the global has a WebSocket property, but
> obviously that is not enough.

You've looked at bug 927481, right? The intention of that bug is to get the right platform support to make our end much simpler.
Attached patch WIP 2 (obsolete) — Splinter Review
Got the window filtering in the content-document-global-created handler working.
Attachment #822853 - Attachment is obsolete: true
Flags: needinfo?(vporof)
Attached patch WIP 3Splinter Review
Now with object actors for data if it is binary data or JSON.parse-able.
Attachment #831076 - Attachment is obsolete: true
aaaaaaaand holy crap testing web socket stuff is not documented at all and looks hard.
Monkey patching the WebSocket constructor and prototype isn't enough, we need to get real platform APIs.
Assignee: nfitzgerald → nobody
Duplicate of this bug: WSFrameInspection
**bump** Saw this on the twitters, a user complaining that a) the websocket tool in chrome is broken and b) it's been that way for a while:

https://twitter.com/davidgasparian/status/458672754334920704
Whiteboard: [status:backlog]
OS: Mac OS X → All
Hardware: x86 → All
I'm mentoring a team of Facebook Open Academy students that want to take a crack at this.

At the platform level, we'll be adding some supervisory interfaces for tracking WebSockets.

At the protocol level, we'll be introducing a new per-tab actor.

At the front end, what we have so far isn't integrated into the Network panel. However, I'm not persuaded that the network panel's structure is well-suited for tracking long-running exchanges. We have something that is more log-like or console-like.

Naturally, everything is open for discussion. We just want to get something up and running quickly; we're prepared to iterate and re-architect as needed to get something that can be landed.
Axel Kratel commented in the Open Academy team's Facebook group:

"Not sure where I should chime in, but I just wanted to make sure that we cover protocol upgrades and frames. In the end, developers would like to see the actual payloads that get transmitted. A large portion of developers will never need raw websocket data because they would be using frameworks like socket.IO which is its own protocol. JSON parsing of websocket data covers at least the socket.IO case, but other popular protocols that run over websocket are STOMP and AMQP."

I replied:

"We'll definitely need ways to display message payloads in a meaningful way. However, if I'm reading the protocol spec correctly, the protocol itself doesn't carry any indication of the type of a message, beyond "text" or "binary". So I'm not sure how our tools can figure out how to display messages. Perhaps we can guess..."

This bug is probably the best place to continue the conversation.
Jim, if websocket is just used to do "send" and "receive" then you can't tell what's in the payload. However, when one uses the upgrade event to a specific protocol over websocket, then you know what the protocol is, and you can use the appropriate parser. 

At the very least, we should allow the parsing of JSON in the websocket data because you can parse those even if you don't know what the protocol is. But it would be nice if the websocket support was written in such a way that it's easy for someone to extend via APIs to add a protocol parser.
I've been consulting RFC6455 to understand what the protocol is capable of conveying:

https://tools.ietf.org/html/rfc6455

That doesn't mention anything about upgrade events. Where are they specified?
Maybe I should clarify: when the upgrade event is fired, you fill the header with "Sec-WebSocket-Protocol:", that tells you what protocol is going to run on top of websocket. Just search the spec for Sec-WebSocket-Protocol. It's actually the one and only upgrade event, since the actual initial WS handshake is handled via http. 

Request URL:ws://xxx
Request Method:GET
Status Code:101 Switching Protocols

Request Headers
Cache-Control:no-cache
Connection:Upgrade
Host:xyz.com:12345
Origin:http://192.168.0.1
Pragma:no-cache
Sec-WebSocket-Key:(unique key)
Sec-WebSocket-Protocol:protocol1:protocol2 <-- browser sends 'I want to speak this protocol, if protocol1 is not available, failover to protocol2'
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent: ... 
 
Response Headers
Connection:Upgrade
Sec-WebSocket-Accept:(unique key)
Sec-WebSocket-Protocol:protocol1           <-- server replies ok, lets use protocol 1
Upgrade:WebSocket

Let me elaborate further. It's nice to be able to use WS to send and receive messages, but that's really not what it was designed for. (this is what happens when you leave  WS was designed so that programmers can select the most appropriate protocol for the task at hand rather than being restricted to doing basic send and receive.

So WS includes the functionality to have an upgrade "handshake" event to a specific protocol that can run on top of websocket. Popular protocols these days include socket.IO, STOMP and AMQP. That happens during the upgrade to WS from the http handshake.

At the very least, the network panel should be able to indicate the protocol during the upgrade event so that the developer knows what protocol is running across the network. In essence, this upgrade even is what can tell the network panel what language is being spoken. But of course when coding, it's possible to say something in "Sec-WebSocket-Protocol" but then speak something else, in which case any parser would spew out gibberish.

The rest consists in writing a parser that can interpret the protocol, i.e. parse out the start and end of payloads and other protocol related information. For example, for STOMP, the payload has headers that say what's in the payload and the protocol indicates what topic or queue the payload is destined for. 

It's obviously not reasonable to expect Mozilla to speak all protocols that are out there. But the network panel would be better served if it included an API that provided access to the frames themselves so that someone can easily write/plugin a protocol parser that could then tell what is being "said", i.e. making sense for what's going across the wire. 

Even without knowing the actual protocol, we can keep things simple and just ship a JSON parser that would provide payload info for any text-based protocol that uses JSON for payloads. 

Whatever we do, we should make it easy for folks to extend and write a parser for Socket.IO, STOMP, AMQP, etc... The socket.IO guys would write one in a heartbeat (no pun intended, there's actually a heartbeat in the socket.IO protocol).

I am sure socket.IO developers would love to see a network panel that could support seeing actual socket.IO events going through the wire. 

If we choose not to provide a way to plugin a parser, I just want to re-emphasize at least the need for at least being able to have frame info, protocol upgrade events and other basic WS events.
Okay, I think I see how this works now: when the web pages makes the connection to the server, it passes a list of "protocol names" that it's willing to speak. Then, in the process of opening the connection, the server selects one of the offered protocol names, and tells the client which one it wants to use. Once the connection has been established, the WebSocket object's 'protocol' property is the name of the protocol the client and server have negotiated.

So we should be able to use the WebSocket's 'protocol' property to select appropriate visualizers for the messages.

I don't think anything we've planned so far would make it at all difficult to add this in the future. I think the first step for us would simply being able to display the messages at all. So we can make this a follow-up bug.

Thanks very much for pointing this out, and for providing great background, Axel.
Depends on: 1103189
Depends on: 1103257
Depends on: WSActors
Whiteboard: [status:backlog] → [status:backlog][devedition-40]
Whiteboard: [status:backlog][devedition-40] → [status:backlog][devedition-40][difficulty=hard]
Priority: P2 → P1
Whiteboard: [status:backlog][devedition-40][difficulty=hard] → [difficulty=hard]
Using this as a tracking bug for general websocket related tools work.
User Story: (updated)
Summary: Allow users to inspect websocket connections in the network monitor → Allow developers to inspect websocket connections
Depends on: WSProtocolParsers
Depends on: WSDiscovery4Tabs
User Story: (updated)
No longer depends on: WSDiscovery4Tabs
Depends on: WSDiscovery4Tabs
Alias: WSInspectorMaster
No longer depends on: 1103189
No longer depends on: 977858
Duplicate of this bug: 1103257
No longer depends on: 1103257
Depends on: WSInterfaceEvents
Keywords: DevAdvocacy
Note that we have already implemented WebSocket Monitor extension
that allows WS monitoring:
https://addons.mozilla.org/cs/firefox/addon/websocket-monitor/

We are planning to integrate this with DevTools, but it isn't a priority for now.

I am lowering the priority of this meta-bug to #2

Honza
Priority: P1 → P2
As decided, meta-bugs don't need priority, removing.

Honza
Priority: P2 → --
Whiteboard: [difficulty=hard] → [difficulty=hard] [DevRel:P1]
Any updates on that? Roadmap or anything? That would be really useful!
(In reply to Jan Honza Odvarko [:Honza] from comment #32)
> Note that we have already implemented WebSocket Monitor extension
> that allows WS monitoring:
> https://addons.mozilla.org/cs/firefox/addon/websocket-monitor/
> 
> We are planning to integrate this with DevTools, but it isn't a priority for
> now.
> 
> I am lowering the priority of this meta-bug to #2
> 
> Honza

This extension is no longer compatible with Firefox 57.
Harald, maybe something to consider for the roadmap, since the suggested add-on no longer works in 57+.
Flags: needinfo?(hkirschner)
We definitely want to support WebSocket debugging again in the future. I expect to revisit this for Q1 planning next year.
Flags: needinfo?(hkirschner)
Working a lot with websocket's for a year, I would like to help on this to make it working. How can I help? Any pointer?
Thank's
Is there a starting point for community to help out here?
Flags: needinfo?(odvarko)
(In reply to :Harald Kirschner :digitarald from comment #39)
> Is there a starting point for community to help out here?
Yes, the home page of WebSocket Monitor extension is the place where to start.
https://github.com/firebug/websocket-monitor

I updated the readme file to explain the current state.

Honza
Flags: needinfo?(odvarko)
Summary: Allow developers to inspect websocket connections → [meta] Allow developers to inspect websocket connections
No longer depends on: WSConsoleLogging
Any news?
Product: Firefox → DevTools
What is the current state of this? This is a must imo!
I think it's done. Can we close this bug or is there something more to do?
Flags: needinfo?(odvarko)
If so, does the changes have been integrated into a nightly build?
With the latest on date - 62.0a1 (2018-06-18) - I am not able to inspect the websocket frames.
So, this actually isn't done (again).

There is an extension allowing WebSocket inspection:
https://github.com/firebug/websocket-monitor

... but, it's based on Add-on SDK and not working anymore.

New extension needs to be implemented on top of WebExtensions API.

One problem is that we have platform API for monitoring WebSocket traffic, but there are no WebExtensions API. So, the final extensions needs an experimental API

Some more links:

Experimental WebExtension - implementing WebSocket API (working prototype)
* https://github.com/janodvarko/webext-websocket-monitor

I am usually posting updates to this thread:
* https://github.com/firebug/websocket-monitor/issues/75

Honza
Flags: needinfo?(odvarko)
I don't know if this is appropriate or even helpful, but this extension works with Firefox Quantum maybe this can help move the bug forward? https://github.com/rinatr1/websocket_sniff

I would really like to be able to debug WS with FF, have to switch to chromium each time I need to do it :/

Honza does your prototype work on recent FF?

We will be picking up this work in the summer (as GSOC project, so it depends on being accepted). Expect bugs to be filed soon.

Stuck on this bug on my development too.

Response payload is empty and same test on Chrome display frames.

There is a plan to solve this, a part of digitarald last comment ?

(In reply to a_pakla from comment #50)

Stuck on this bug on my development too.

Response payload is empty and same test on Chrome display frames.

There is a plan to solve this, a part of digitarald last comment ?

Yes, Mozilla has been accepted as a mentoring organization and the project should happen June - August.

Honza

Alias: WSInspectorMaster → network-websocket-inspector
Summary: [meta] Allow developers to inspect websocket connections → [meta] Websocket frame inspection in Netmonitor
Duplicate of this bug: 1493147
Duplicate of this bug: WSInterfaceEvents
Duplicate of this bug: WSDiscovery4Tabs
Duplicate of this bug: WSGenericPayloadParsing
Duplicate of this bug: WSProtocolParsers
Duplicate of this bug: WSActors
Depends on: 1561676
Depends on: 1563470
No longer blocks: 1564105
Depends on: 1564105
No longer blocks: 1493147
Depends on: 1565499
No longer depends on: 1565499
Depends on: 1566002

Just for the record. The entire WebSocket support is currently implemented behind a pref: devtools.netmonitor.features.webSockets
Honza

Depends on: 1566243
Depends on: 1566525
Depends on: 1566775
Depends on: 1566780
Depends on: 1566788

Hello, thank you all for working on this! I've been missing this in Firefox and even the current working version is miles ahead of Chrome already. A few things that I think might be worth adding (apologies if these have been proposed already / elsewhere) :

  1. WebSockets support extensions which are negotiated during the initial handshake. It would be great if I could see which extensions have the parties agreed upon and are in use.
  2. One of the extensions is "permessage-deflate" and I can imagine this being fairly commonly used. It would be great if there was a "Compressed Size" column in the Messages tab (not available if the extension is not in use and hidden by default).
Depends on: 1567606
Depends on: 1567608
Depends on: 1567633
Depends on: 1569781
No longer depends on: 1569781
No longer depends on: 1566775
Depends on: 1575465
Depends on: 1575464
No longer depends on: 1560421
Depends on: 1583069
Depends on: 1588859
Depends on: 1588996
No longer depends on: net-ws-perf
Depends on: 1591910
Depends on: 1590223
Depends on: 1589432
Depends on: 1593830
Depends on: 1593831
Depends on: 1593837
See Also: → 1405706
Summary: [meta] Websocket frame inspection in Netmonitor → [meta] Websocket frame inspection
Summary: [meta] Websocket frame inspection → [meta] WebSocket Inspector
You need to log in before you can comment on or make changes to this bug.