-
Notifications
You must be signed in to change notification settings - Fork 30k
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
inspector: add initial support for network inspection #53593
Merged
nodejs-github-bot
merged 17 commits into
nodejs:main
from
cola119:network-inspection-poc
Jul 19, 2024
Merged
Changes from 16 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
6d02220
inspector: add initial support for network inspection
cola119 5cfddc3
inspector: add a document and a test for `inspector.emitProtocolEvent`
cola119 6f8e347
inspector: introduce `--experimental-network-inspection`
cola119 c7a7e59
inspector: drop support for response body inspection
cola119 2807265
inspector: enable/disable network tracking on NodeNetwork.enable/disable
cola119 6a80de6
inspector: add APIs for NodeNetwork events
cola119 54f6650
test: workaround for `skipIfInspectorDisabled` issue in without-ssl b…
cola119 afc4dbb
cli: remove `--experimental-network-inspection` from NODE_OPTIONS
cola119 658318d
inspector: correctly enable/disable `NodeNetwork` domain via `Network…
cola119 877e68c
inspector: fix the failure of `tools/test.py --worker`
cola119 5c058f9
lint fix
cola119 0bf5221
inspector: check `--experimental-network-inspection` in `pre_executio…
cola119 4103e26
inspector: refactor to define `NetworkInspector`
cola119 47f3ae9
Update docs
cola119 030f025
inspector: rename to `broadcastToFrontend`
cola119 1796860
Update docs
cola119 1c6fc6c
inspector: remove redundant `NodeNetwork` domain, consolidate with `N…
cola119 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
'use strict'; | ||
|
||
const { | ||
DateNow, | ||
} = primordials; | ||
|
||
let dc; | ||
let NodeNetwork; | ||
|
||
let requestId = 0; | ||
const getNextRequestId = () => `node-network-event-${++requestId}`; | ||
|
||
function onClientRequestStart({ request }) { | ||
const url = `${request.protocol}//${request.host}${request.path}`; | ||
const wallTime = DateNow(); | ||
const timestamp = wallTime / 1000; | ||
request._inspectorRequestId = getNextRequestId(); | ||
NodeNetwork.requestWillBeSent({ | ||
requestId: request._inspectorRequestId, | ||
timestamp, | ||
wallTime, | ||
request: { | ||
url, | ||
method: request.method, | ||
}, | ||
}); | ||
} | ||
|
||
function onClientResponseFinish({ request }) { | ||
if (typeof request._inspectorRequestId !== 'string') { | ||
return; | ||
} | ||
const timestamp = DateNow() / 1000; | ||
NodeNetwork.responseReceived({ | ||
requestId: request._inspectorRequestId, | ||
timestamp, | ||
}); | ||
NodeNetwork.loadingFinished({ | ||
requestId: request._inspectorRequestId, | ||
timestamp, | ||
}); | ||
} | ||
|
||
function enable() { | ||
if (!dc) { | ||
dc = require('diagnostics_channel'); | ||
} | ||
if (!NodeNetwork) { | ||
NodeNetwork = require('inspector').NodeNetwork; | ||
} | ||
dc.subscribe('http.client.request.start', onClientRequestStart); | ||
dc.subscribe('http.client.response.finish', onClientResponseFinish); | ||
} | ||
|
||
function disable() { | ||
dc.unsubscribe('http.client.request.start', onClientRequestStart); | ||
dc.unsubscribe('http.client.response.finish', onClientResponseFinish); | ||
} | ||
|
||
module.exports = { | ||
enable, | ||
disable, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#include "network_agent.h" | ||
#include "network_inspector.h" | ||
|
||
namespace node { | ||
namespace inspector { | ||
namespace protocol { | ||
|
||
std::unique_ptr<Network::Request> Request(const String& url, | ||
const String& method) { | ||
return Network::Request::create().setUrl(url).setMethod(method).build(); | ||
} | ||
|
||
NetworkAgent::NetworkAgent(NetworkInspector* inspector) | ||
: inspector_(inspector) { | ||
event_notifier_map_["requestWillBeSent"] = &NetworkAgent::requestWillBeSent; | ||
event_notifier_map_["responseReceived"] = &NetworkAgent::responseReceived; | ||
event_notifier_map_["loadingFinished"] = &NetworkAgent::loadingFinished; | ||
} | ||
|
||
void NetworkAgent::emitNotification( | ||
const String& event, std::unique_ptr<protocol::DictionaryValue> params) { | ||
if (!inspector_->IsEnabled()) return; | ||
auto it = event_notifier_map_.find(event); | ||
if (it != event_notifier_map_.end()) { | ||
(this->*(it->second))(std::move(params)); | ||
} | ||
} | ||
|
||
void NetworkAgent::Wire(UberDispatcher* dispatcher) { | ||
frontend_ = std::make_unique<Network::Frontend>(dispatcher->channel()); | ||
Network::Dispatcher::wire(dispatcher, this); | ||
} | ||
|
||
DispatchResponse NetworkAgent::enable() { | ||
inspector_->Enable(); | ||
return DispatchResponse::OK(); | ||
} | ||
|
||
DispatchResponse NetworkAgent::disable() { | ||
inspector_->Disable(); | ||
return DispatchResponse::OK(); | ||
} | ||
|
||
void NetworkAgent::requestWillBeSent( | ||
std::unique_ptr<protocol::DictionaryValue> params) { | ||
String request_id; | ||
params->getString("requestId", &request_id); | ||
double timestamp; | ||
params->getDouble("timestamp", ×tamp); | ||
double wall_time; | ||
params->getDouble("wallTime", &wall_time); | ||
auto request = params->getObject("request"); | ||
String url; | ||
request->getString("url", &url); | ||
String method; | ||
request->getString("method", &method); | ||
|
||
frontend_->requestWillBeSent( | ||
request_id, Request(url, method), timestamp, wall_time); | ||
} | ||
|
||
void NetworkAgent::responseReceived( | ||
std::unique_ptr<protocol::DictionaryValue> params) { | ||
String request_id; | ||
params->getString("requestId", &request_id); | ||
double timestamp; | ||
params->getDouble("timestamp", ×tamp); | ||
|
||
frontend_->responseReceived(request_id, timestamp); | ||
} | ||
|
||
void NetworkAgent::loadingFinished( | ||
std::unique_ptr<protocol::DictionaryValue> params) { | ||
String request_id; | ||
params->getString("requestId", &request_id); | ||
double timestamp; | ||
params->getDouble("timestamp", ×tamp); | ||
|
||
frontend_->loadingFinished(request_id, timestamp); | ||
} | ||
|
||
} // namespace protocol | ||
} // namespace inspector | ||
} // namespace node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#ifndef SRC_INSPECTOR_NETWORK_AGENT_H_ | ||
#define SRC_INSPECTOR_NETWORK_AGENT_H_ | ||
|
||
#include "node/inspector/protocol/Network.h" | ||
|
||
#include <unordered_map> | ||
|
||
namespace node { | ||
|
||
namespace inspector { | ||
class NetworkInspector; | ||
|
||
namespace protocol { | ||
|
||
std::unique_ptr<Network::Request> Request(const String& url, | ||
const String& method); | ||
|
||
class NetworkAgent : public Network::Backend { | ||
public: | ||
explicit NetworkAgent(NetworkInspector* inspector); | ||
|
||
void Wire(UberDispatcher* dispatcher); | ||
|
||
DispatchResponse enable() override; | ||
|
||
DispatchResponse disable() override; | ||
|
||
void emitNotification(const String& event, | ||
std::unique_ptr<protocol::DictionaryValue> params); | ||
|
||
void requestWillBeSent(std::unique_ptr<protocol::DictionaryValue> params); | ||
|
||
void responseReceived(std::unique_ptr<protocol::DictionaryValue> params); | ||
|
||
void loadingFinished(std::unique_ptr<protocol::DictionaryValue> params); | ||
|
||
private: | ||
NetworkInspector* inspector_; | ||
std::shared_ptr<Network::Frontend> frontend_; | ||
using EventNotifier = | ||
void (NetworkAgent::*)(std::unique_ptr<protocol::DictionaryValue>); | ||
std::unordered_map<String, EventNotifier> event_notifier_map_; | ||
}; | ||
|
||
} // namespace protocol | ||
} // namespace inspector | ||
} // namespace node | ||
|
||
#endif // SRC_INSPECTOR_NETWORK_AGENT_H_ |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried it out today when I had free time. Is it possible to retrieve the original call location from the stack obtained in this way, which indicates
diagnostics_channel
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does 'the original call location' refer to the location in the user script where the network activity started? I mean, are you looking to retrieve the location indicated below?
If so, I think it's difficult with the current
diagnostics_channel
API. cc @nodejs/diagnosticsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I mean it's not easy to do with dc.