Skip to content

Commit 6a9a7cf

Browse files
committed
inspector: add initial support for network inspection
1 parent 4c730ae commit 6a9a7cf

11 files changed

+484
-2
lines changed

lib/_http_client.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
const {
2525
ArrayIsArray,
2626
Boolean,
27+
DateNow,
2728
Error,
2829
FunctionPrototypeCall,
2930
NumberIsFinite,
@@ -70,6 +71,7 @@ const {
7071
isTraceHTTPEnabled,
7172
traceBegin,
7273
traceEnd,
74+
getNextInspectorEventId,
7375
getNextTraceEventId,
7476
} = require('internal/http');
7577
const {
@@ -93,6 +95,14 @@ const {
9395
stopPerf,
9496
} = require('internal/perf/observe');
9597

98+
const {
99+
isEnabled: isInspectorEnabled,
100+
requestWillBeSent,
101+
responseReceived,
102+
dataReceived,
103+
loadingFinished,
104+
} = internalBinding('inspector');
105+
96106
const kClientRequestStatistics = Symbol('ClientRequestStatistics');
97107

98108
const dc = require('diagnostics_channel');
@@ -375,14 +385,15 @@ ObjectSetPrototypeOf(ClientRequest, OutgoingMessage);
375385

376386
ClientRequest.prototype._finish = function _finish() {
377387
FunctionPrototypeCall(OutgoingMessage.prototype._finish, this);
388+
const url = `${this.protocol}//${this.host}${this.path}`;
378389
if (hasObserver('http')) {
379390
startPerf(this, kClientRequestStatistics, {
380391
type: 'http',
381392
name: 'HttpClient',
382393
detail: {
383394
req: {
384395
method: this.method,
385-
url: `${this.protocol}//${this.host}${this.path}`,
396+
url,
386397
headers: typeof this.getHeaders === 'function' ? this.getHeaders() : {},
387398
},
388399
},
@@ -393,6 +404,14 @@ ClientRequest.prototype._finish = function _finish() {
393404
request: this,
394405
});
395406
}
407+
408+
if (isInspectorEnabled()) {
409+
this._inspectorEventId = getNextInspectorEventId();
410+
const wallTime = DateNow();
411+
const timestamp = wallTime / 1000;
412+
requestWillBeSent(this._inspectorEventId, url, this.method, timestamp, wallTime);
413+
}
414+
396415
if (isTraceHTTPEnabled()) {
397416
this._traceEventId = getNextTraceEventId();
398417
traceBegin(HTTP_CLIENT_TRACE_EVENT_NAME, this._traceEventId);
@@ -680,6 +699,21 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
680699
response: res,
681700
});
682701
}
702+
703+
if (isInspectorEnabled() && typeof req._inspectorEventId === 'string') {
704+
responseReceived(req._inspectorEventId, DateNow() / 1000);
705+
let response = '';
706+
const onData = (chunk) => {
707+
dataReceived(req._inspectorEventId, DateNow() / 1000, chunk.length);
708+
response += chunk.toString();
709+
};
710+
res.on('data', onData);
711+
res.on('end', () => {
712+
loadingFinished(req._inspectorEventId, response, DateNow() / 1000, response.length);
713+
res.removeListener('data', onData);
714+
});
715+
}
716+
683717
if (isTraceHTTPEnabled() && typeof req._traceEventId === 'number') {
684718
traceEnd(HTTP_CLIENT_TRACE_EVENT_NAME, req._traceEventId, {
685719
path: req.path,

lib/internal/http.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ function resetCache() {
3131
utcCache = undefined;
3232
}
3333

34+
let inspectorEventId = 0;
35+
36+
function getNextInspectorEventId() {
37+
const id = ++inspectorEventId;
38+
return `node-network-inspect-event-${id}`;
39+
}
40+
3441
let traceEventId = 0;
3542

3643
function getNextTraceEventId() {
@@ -57,6 +64,7 @@ module.exports = {
5764
utcDate,
5865
traceBegin,
5966
traceEnd,
67+
getNextInspectorEventId,
6068
getNextTraceEventId,
6169
isTraceHTTPEnabled,
6270
};

src/inspector/network_agent.cc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include "network_agent.h"
2+
3+
#include "inspector_agent.h"
4+
5+
namespace node {
6+
namespace inspector {
7+
namespace protocol {
8+
9+
std::unique_ptr<Network::Request> Request(const String& url,
10+
const String& method) {
11+
return Network::Request::create().setUrl(url).setMethod(method).build();
12+
}
13+
14+
NetworkAgent::NetworkAgent() {}
15+
16+
void NetworkAgent::Wire(UberDispatcher* dispatcher) {
17+
frontend_ = std::make_unique<Network::Frontend>(dispatcher->channel());
18+
Network::Dispatcher::wire(dispatcher, this);
19+
}
20+
21+
DispatchResponse NetworkAgent::getResponseBody(const String& in_requestId,
22+
String* out_body) {
23+
auto it = request_id_to_response_.find(in_requestId);
24+
if (it != request_id_to_response_.end()) {
25+
*out_body = it->second;
26+
}
27+
return DispatchResponse::OK();
28+
}
29+
30+
void NetworkAgent::requestWillBeSent(const String& request_id,
31+
const String& url,
32+
const String& method,
33+
double timestamp,
34+
double wall_time) {
35+
frontend_->requestWillBeSent(
36+
request_id, Request(url, method), timestamp, wall_time);
37+
}
38+
39+
void NetworkAgent::responseReceived(const String& request_id,
40+
double timestamp) {
41+
frontend_->responseReceived(request_id, timestamp);
42+
}
43+
44+
void NetworkAgent::dataReceived(const String& request_id,
45+
double timestamp,
46+
int data_length) {
47+
frontend_->dataReceived(request_id, timestamp, data_length);
48+
}
49+
50+
void NetworkAgent::loadingFinished(const String& request_id,
51+
const String& response,
52+
double timestamp,
53+
int encoded_data_length) {
54+
request_id_to_response_[request_id] = response;
55+
frontend_->loadingFinished(request_id, timestamp, encoded_data_length);
56+
}
57+
58+
} // namespace protocol
59+
} // namespace inspector
60+
} // namespace node

src/inspector/network_agent.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#ifndef SRC_INSPECTOR_NETWORK_AGENT_H_
2+
#define SRC_INSPECTOR_NETWORK_AGENT_H_
3+
4+
#include "node/inspector/protocol/Network.h"
5+
#include "v8.h"
6+
7+
#include <unordered_map>
8+
9+
namespace node {
10+
11+
namespace inspector {
12+
namespace protocol {
13+
14+
class NetworkAgent : public Network::Backend {
15+
public:
16+
NetworkAgent();
17+
18+
void Wire(UberDispatcher* dispatcher);
19+
20+
DispatchResponse getResponseBody(const String& in_requestId,
21+
String* out_body) override;
22+
23+
void requestWillBeSent(const String& request_id,
24+
const String& url,
25+
const String& method,
26+
double timestamp,
27+
double wall_time);
28+
29+
void responseReceived(const String& request_id, double timestamp);
30+
31+
void dataReceived(const String& request_id,
32+
double timestamp,
33+
int data_length);
34+
35+
void loadingFinished(const String& request_id,
36+
const String& response,
37+
double timestamp,
38+
int encoded_data_length);
39+
40+
private:
41+
std::shared_ptr<Network::Frontend> frontend_;
42+
std::unordered_map<String, String> request_id_to_response_;
43+
};
44+
45+
} // namespace protocol
46+
} // namespace inspector
47+
} // namespace node
48+
49+
#endif // SRC_INSPECTOR_NETWORK_AGENT_H_

src/inspector/node_inspector.gypi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
'src/inspector/tracing_agent.h',
2424
'src/inspector/worker_agent.cc',
2525
'src/inspector/worker_agent.h',
26+
'src/inspector/network_agent.cc',
27+
'src/inspector/network_agent.h',
2628
'src/inspector/worker_inspector.cc',
2729
'src/inspector/worker_inspector.h',
2830
],
@@ -36,6 +38,8 @@
3638
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeTracing.h',
3739
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeRuntime.cpp',
3840
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeRuntime.h',
41+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.cpp',
42+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.h',
3943
],
4044
'node_protocol_files': [
4145
'<(protocol_tool_path)/lib/Allocator_h.template',

src/inspector/node_protocol.pdl

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,71 @@ experimental domain NodeWorker
9898
SessionID sessionId
9999
string message
100100

101+
# Partial support for Network domain of ChromeDevTools Protocol.
102+
# https://chromedevtools.github.io/devtools-protocol/tot/Network
103+
experimental domain Network
104+
# Unique request identifier.
105+
type RequestId extends string
106+
107+
# UTC time in seconds, counted from January 1, 1970.
108+
type TimeSinceEpoch extends number
109+
110+
# Monotonically increasing time in seconds since an arbitrary point in the past.
111+
type MonotonicTime extends number
112+
113+
# HTTP request data.
114+
type Request extends object
115+
properties
116+
string url
117+
string method
118+
119+
# Returns content served for the given request.
120+
command getResponseBody
121+
parameters
122+
# Identifier of the network request to get content for.
123+
RequestId requestId
124+
returns
125+
# Response body.
126+
string body
127+
128+
# Fired when page is about to send HTTP request.
129+
event requestWillBeSent
130+
parameters
131+
# Request identifier.
132+
RequestId requestId
133+
# Request data.
134+
Request request
135+
# Timestamp.
136+
MonotonicTime timestamp
137+
# Timestamp.
138+
TimeSinceEpoch wallTime
139+
140+
# Fired when HTTP response is available.
141+
event responseReceived
142+
parameters
143+
# Request identifier.
144+
RequestId requestId
145+
# Timestamp.
146+
MonotonicTime timestamp
147+
148+
event dataReceived
149+
parameters
150+
# Request identifier.
151+
RequestId requestId
152+
# Timestamp.
153+
MonotonicTime timestamp
154+
# Data chunk length.
155+
integer dataLength
156+
157+
event loadingFinished
158+
parameters
159+
# Request identifier.
160+
RequestId requestId
161+
# Timestamp.
162+
MonotonicTime timestamp
163+
# Total number of bytes received for this request.
164+
number encodedDataLength
165+
101166
# Support for inspecting node process state.
102167
experimental domain NodeRuntime
103168
# Enable the NodeRuntime events except by `NodeRuntime.waitingForDisconnect`.

src/inspector/node_string.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ String StringViewToUtf8(v8_inspector::StringView view) {
8484
String fromDouble(double d) {
8585
std::ostringstream stream;
8686
stream.imbue(std::locale::classic()); // Ignore current locale
87-
stream << d;
87+
stream << std::fixed << d;
8888
return stream.str();
8989
}
9090

0 commit comments

Comments
 (0)