diagnostics icon indicating copy to clipboard operation
diagnostics copied to clipboard

Support Network Inspection

Open eugeneo opened this issue 9 years ago • 65 comments

Network domain is what Chrome DevTools (and any other interested frontends) use for inspecting the HTTP and WS traffic in the browser. This document provides some insight into Chrome DevTools UI and here is a description of the protocol for obtaining that data.

We propose to introduce a Node specific agent that would expose the same (or subset) of this protocol to enable the UI. It does not seem possible to share the implementation between Blink and Node.js.

This agent would also introduce an API for the modules to report the events. E.g. WebSocket modules should be able to notify the agent when WS frames are sent or received.

eugeneo avatar Dec 01 '16 00:12 eugeneo

would be great to have support for node tcp/udp as well, not sure if that can fit into existing UI and debugger protocol

sidorares avatar Dec 01 '16 01:12 sidorares

Would it make sense to use trace events as the interface to the agent? That would also provide an interface for 3rd party modules (e.g. Websocket) out-of-the-box.

I'm not sure if tcp/udp would become confusing because it's another level than the others. Would http requests show up twice effectively? But having a story for things like memcached's TCP protocol would be great. The obvious/hacky solution would be for them to pretend to be websocket frames.

hybrist avatar Dec 01 '16 16:12 hybrist

Looks like trace events might be usable for this. HTTP requests/responses might get quite big - I wonder if there's any limit on event sizes...

+@matthewloring, @ofrobots - would it be possible to use the trace events framework for this? E.g. inspector would have an agent that "listens" on event categories and then sends inspector protocol notifications.

eugeneo avatar Dec 01 '16 22:12 eugeneo

One thing I ran into with a similar feature in bugger: Retaining all request and response bodies in the process can become problematic, especially when there's no easy way to disable it. E.g. "hey let me profile this app while sending a couple of thousand of requests through it to find that memory leak" - aaand you're running out of memory because all request/response bodies are being kept in memory by the agent.

hybrist avatar Dec 02 '16 14:12 hybrist

There is not currently a mechanism for observing trace events as they are generated. We could explore this in the future once the design in https://github.com/nodejs/node/pull/9304 solidifies.

matthewloring avatar Dec 02 '16 15:12 matthewloring

Would it be possible to monkey patch this? Similar to how node inspector does it?

alnorris avatar Feb 24 '17 10:02 alnorris

@alnorris honestly it looks like the existing monkeypatch from node-inspector (Injections/NetworkAgent.js) would get pretty far.

The emitted events would just need to make their way to the InspectorAgent

paulirish avatar Feb 26 '17 03:02 paulirish

My architecture proposal in https://github.com/nodejs/node/issues/7393 is largely about allowing implementation of Domain.Method dispatchers other than those tied directly to V8, which is all we have now. The Network domain implementation we're discussing in this thread could be handled by just such an alternate dispatcher if our architecture allowed it.

Allowing alternate dispatchers would a) allow complete alternate implementations, e.g. for other runtimes like Chakra or SpiderMonkey; and b) facilitate one-off (monkey-patched?) alternate or additional implementations for specific Domains and Methods.

/cc @kfarnung who's been looking into such a rearchitecture and Inspector's impact on e.g. Node-ChakraCore more deeply.

joshgav avatar Feb 27 '17 15:02 joshgav

Perhaps a way to facilitate inspector "addons" would be to update NodeInspectorClient::dispatchMessageFromFrontend to route based on the Domain name. That is, Debugger, Profiler, Runtime, and all the domains handled by V8 would be routed to V8Inspector as they are now; and others like Network could be routed elsewhere.

joshgav avatar May 11 '17 17:05 joshgav

@eugeneo I changed the title so it would be more obvious what this issue is about, please change back if you disagree. Thanks!

joshgav avatar May 11 '17 17:05 joshgav

@joshgav I agree. I want to look into JS handlers for the inspector messages. Currently I am waiting for the inspector JS API PR to land.

eugeneo avatar May 11 '17 17:05 eugeneo

Was there any movement on this? I think it would be a really great feature. It looks like in Chrome there's a pretty straight-forward check (InspectorSession::DispatchProtocolMessage):

void InspectorSession::DispatchProtocolMessage(const String& method,
                                               const String& message) {
  DCHECK(!disposed_);
  if (v8_inspector::V8InspectorSession::canDispatchMethod(
          ToV8InspectorStringView(method))) {
    v8_session_->dispatchProtocolMessage(ToV8InspectorStringView(message));
  } else {
    inspector_backend_dispatcher_->dispatch(
        protocol::StringUtil::parseJSON(message));
  }
}

We could "just" introduce an extension to the existing inspector JS API that allows to register additional handlers. Or, alternatively, a C++ API for the same (might be less confusing when it comes to execution / threads).

The idea here is that we could start with opening up an experimental low-level API and then later decide if and what kind of node-specific dispatchers we'd want.

hybrist avatar Oct 24 '17 21:10 hybrist

Right now I am working on custom protocol handlers on the Node side. I am implementing "Target" domain (that should allow debugging child processes). "Network" domain can be implemented afterwards, but it would require effort from module writers - e.g. WebSocket implementors will need to specifically report WS frames.

eugeneo avatar Oct 24 '17 22:10 eugeneo

@jkrems - this is the Node counterpart - https://github.com/eugeneo/node/blob/df8e41d3be705410e3a3389b8660b3289e25399f/src/inspector_agent.cc#L255

Minor difference is that I am passing unrecognized messages to V8 dispatcher to reuse "method not found" notification.

eugeneo avatar Oct 24 '17 22:10 eugeneo

Chrome DevTools tech writer here. Just talked to somebody who's using node --inspect to debug his Node server via DevTools. He was looking for the Network panel, and was confused why it was missing. His goal was to debug the network requests that his server was making. Seems like a reasonable use case to me!

kaycebasques avatar Oct 26 '17 17:10 kaycebasques

Any update?

nmiddendorff avatar Jun 26 '18 20:06 nmiddendorff

Many of us would love to know, there are two medium articles which did not age particularly well and beyond that not much of a page on the internet to explain YES THIS is how you inspect http requests through node with the same powers as chrome network inspector tab.

this nodejs page in the docs for example references cancelled or unsupported projects for the last 2-3 versions of node https://nodejs.org/en/docs/guides/debugging-getting-started/

How can we users help ensure there is a place on the internet for users to find timely documentation on inspection of http requests and options.

Kielan avatar Sep 12 '18 01:09 Kielan

@Kielan thanks for weighting in! I don't think it's currently possible to see the HTTP requests in the inspector, so there is no place where this is documented. Possibly, we should document that no, it is not possible to inspect http requests and responses. However, work is being carried on to enable this.

Considering that we can now route trace_events into the inspector (https://github.com/nodejs/node/pull/20608). @eugeneo would that be enough to add this support to the inspector? Do you need any specific data/in a specific format to be able to render HTTP requests?

mcollina avatar Sep 12 '18 06:09 mcollina

Chrome has a well-define protocol for inspecting network - https://chromedevtools.github.io/devtools-protocol/tot/Network

It should not be too hard to write a handler that will handle the messages, the bigger problem is gathering the data. This may need an effort from some community packages, e.g. WebSocket packages will need to report events to Inspector, maybe something will need to be done to Express (though I expect HTTP support only needs instrumentation in the standard library)

eugeneo avatar Sep 12 '18 15:09 eugeneo

@eugeneo that seem very much focus on outgoing requests and not incoming, i.e. http clients vs http servers. How those will be displayed? Gathering the data would not be very hard with async_hooks or by plugging it into our internals, I can help with that.

mcollina avatar Sep 12 '18 16:09 mcollina

Chrome protocol records both requests and responses.

eugeneo avatar Sep 12 '18 16:09 eugeneo

@eugeneo I don't think I've been clear enough, so let me ask with more details. In Node.js we have IncomingMessage and OutgoingMessage. The usage of those is swapped between the client and the server, so that a request on the client inherits from OutgoingMessage, while a request received by the server inherits from IncomingMessage (and vice versa for the responses). The inspector only have 2 types, Request and Response. How would you map the Node.js types to the Chrome protocol types?

If you have time, an example of sending that data from Node.js to the inspector would be brilliant, I'll see if I can do a prototype.

mcollina avatar Sep 12 '18 16:09 mcollina

Not sure what difference would that be - Response always comes after the Request, on server or client.

There are likely some gotchas that can only be understood when the implementation is done. NodeTracing (and pending NodeWorker) domains are not 100% copies of the Chrome protocol, so NodeNetwork would be able to reflect specifics.

eugeneo avatar Sep 12 '18 16:09 eugeneo

I'm confident that I can get that data out, is it possible right now to send that data to the inspector?

mcollina avatar Sep 12 '18 16:09 mcollina

No. Inspector will need a new "domain" added - e.g. https://github.com/nodejs/node/pull/21364/commits/dc1822d5ed2962b81ee776769f03087a3de50ff0

eugeneo avatar Sep 12 '18 16:09 eugeneo

The inspector only have 2 types, Request and Response. How would you map the Node.js types to the Chrome protocol types?

Maybe always map the request to Request and the response to the Response (regardless of the exchange was initiated by the node process or by an external client, but allow filtering Incoming vs Outgoing requests?

nicoburns avatar Sep 12 '18 16:09 nicoburns

It should not be too hard to write a handler that will handle the messages, the bigger problem is gathering the data.

@eugeneo would you like to work together on this? I think we can solve the two pieces of the puzzle, as I think getting the data is feasible. I would recommend focusing on Request and Response from http first, and discuss websocket later.

mcollina avatar Sep 12 '18 16:09 mcollina

@mcollina I can help with navigating inspector code and code reviews.

(UPD: slight edit)

eugeneo avatar Sep 12 '18 21:09 eugeneo

@mcollina - is this the issue you wanted added to diag agenda?

mike-kaufman avatar Nov 28 '18 23:11 mike-kaufman

Yes thanks!

Il giorno gio 29 nov 2018 alle 00:51 Mike Kaufman [email protected] ha scritto:

@mcollina https://github.com/mcollina - is this the issue you wanted added to diag agenda?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nodejs/diagnostics/issues/75#issuecomment-442651223, or mute the thread https://github.com/notifications/unsubscribe-auth/AADL4zq9djVthHTUeU41eRwgsLAPa87-ks5uzyGLgaJpZM4LA3is .

mcollina avatar Nov 29 '18 05:11 mcollina