Skip to content

Commit cb7453f

Browse files
huntiefacebook-github-bot
authored andcommitted
Improve Network trace event field coverage (#53840)
Summary: Pull Request resolved: #53840 After this diff, successful network events are displayed as fully hydrated timespans in the Performance panel network track, with all metadata needed to usefully populate the UI. **Changes** Adds: - `"ResourceFinish"`: `encodedDataLength`, `decodedBodyLength` - `"ResourceReceiveResponse"`: Populates `data.timing` members, which enables *"Request sent and waiting"* to be rendered correctly in the timeline. Removes: - `"ResourceWillSendRequest"` events — very rarely emitted by Chrome and are extraneous for our use case. Changelog: [Internal] Reviewed By: hoxyq Differential Revision: D82636798 fbshipit-source-id: a4b0f0671b97aaadc279ac56d39fee0c95d4ddc7
1 parent c8e5f97 commit cb7453f

File tree

3 files changed

+90
-88
lines changed

3 files changed

+90
-88
lines changed

packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -238,25 +238,6 @@ void PerformanceTracer::reportEventLoopMicrotasks(
238238
});
239239
}
240240

241-
void PerformanceTracer::reportResourceWillSendRequest(
242-
const std::string& devtoolsRequestId,
243-
HighResTimeStamp start) {
244-
if (!tracingAtomic_) {
245-
return;
246-
}
247-
248-
std::lock_guard<std::mutex> lock(mutex_);
249-
if (!tracingAtomic_) {
250-
return;
251-
}
252-
253-
enqueueEvent(PerformanceTracerResourceWillSendRequest{
254-
.requestId = devtoolsRequestId,
255-
.start = start,
256-
.threadId = getCurrentThreadId(),
257-
});
258-
}
259-
260241
void PerformanceTracer::reportResourceSendRequest(
261242
const std::string& devtoolsRequestId,
262243
HighResTimeStamp start,
@@ -290,7 +271,8 @@ void PerformanceTracer::reportResourceReceiveResponse(
290271
HighResTimeStamp start,
291272
int statusCode,
292273
const Headers& headers,
293-
int encodedDataLength) {
274+
int encodedDataLength,
275+
folly::dynamic timingData) {
294276
if (!tracingAtomic_) {
295277
return;
296278
}
@@ -308,13 +290,16 @@ void PerformanceTracer::reportResourceReceiveResponse(
308290
.mimeType = jsinspector_modern::mimeTypeFromHeaders(headers),
309291
.protocol = "h2",
310292
.statusCode = statusCode,
293+
.timing = std::move(timingData),
311294
.threadId = getCurrentThreadId(),
312295
});
313296
}
314297

315298
void PerformanceTracer::reportResourceFinish(
316299
const std::string& devtoolsRequestId,
317-
HighResTimeStamp start) {
300+
HighResTimeStamp start,
301+
int encodedDataLength,
302+
int decodedBodyLength) {
318303
if (!tracingAtomic_) {
319304
return;
320305
}
@@ -327,6 +312,8 @@ void PerformanceTracer::reportResourceFinish(
327312
enqueueEvent(PerformanceTracerResourceFinish{
328313
.requestId = devtoolsRequestId,
329314
.start = start,
315+
.encodedDataLength = encodedDataLength,
316+
.decodedBodyLength = decodedBodyLength,
330317
.threadId = getCurrentThreadId(),
331318
});
332319
}
@@ -604,21 +591,6 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
604591
.args = folly::dynamic::object("data", std::move(data)),
605592
});
606593
},
607-
[&](PerformanceTracerResourceWillSendRequest&& event) {
608-
folly::dynamic data =
609-
folly::dynamic::object("requestId", std::move(event.requestId));
610-
611-
events.emplace_back(TraceEvent{
612-
.name = "ResourceWillSendRequest",
613-
.cat = "devtools.timeline",
614-
.ph = 'I',
615-
.ts = event.start,
616-
.pid = processId_,
617-
.s = 't',
618-
.tid = event.threadId,
619-
.args = folly::dynamic::object("data", std::move(data)),
620-
});
621-
},
622594
[&](PerformanceTracerResourceSendRequest&& event) {
623595
folly::dynamic data =
624596
folly::dynamic::object("initiator", folly::dynamic::object())(
@@ -651,7 +623,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
651623
"protocol", event.protocol)(
652624
"requestId", std::move(event.requestId))(
653625
"statusCode", event.statusCode)(
654-
"timing", folly::dynamic::object());
626+
"timing", std::move(event.timing));
655627

656628
events.emplace_back(TraceEvent{
657629
.name = "ResourceReceiveResponse",
@@ -665,7 +637,9 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
665637
});
666638
},
667639
[&](PerformanceTracerResourceFinish&& event) {
668-
folly::dynamic data = folly::dynamic::object("didFail", false)(
640+
folly::dynamic data = folly::dynamic::object(
641+
"decodedBodyLength", event.decodedBodyLength)("didFail", false)(
642+
"encodedDataLength", event.encodedDataLength)(
669643
"requestId", std::move(event.requestId));
670644

671645
events.emplace_back(TraceEvent{

packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ class PerformanceTracer {
148148
HighResTimeStamp start,
149149
int statusCode,
150150
const Headers& headers,
151-
int encodedDataLength);
151+
int encodedDataLength,
152+
folly::dynamic timingData);
152153

153154
/**
154155
* Record a "ResourceFinish" event. Paired with other "Resource*" events,
@@ -158,7 +159,9 @@ class PerformanceTracer {
158159
*/
159160
void reportResourceFinish(
160161
const std::string& devtoolsRequestId,
161-
HighResTimeStamp start);
162+
HighResTimeStamp start,
163+
int encodedDataLength,
164+
int decodedBodyLength);
162165

163166
/**
164167
* Creates "Profile" Trace Event.
@@ -233,13 +236,6 @@ class PerformanceTracer {
233236
HighResTimeStamp createdAt = HighResTimeStamp::now();
234237
};
235238

236-
struct PerformanceTracerResourceWillSendRequest {
237-
std::string requestId;
238-
HighResTimeStamp start;
239-
ThreadId threadId;
240-
HighResTimeStamp createdAt = HighResTimeStamp::now();
241-
};
242-
243239
struct PerformanceTracerResourceSendRequest {
244240
std::string requestId;
245241
std::string url;
@@ -253,6 +249,8 @@ class PerformanceTracer {
253249
struct PerformanceTracerResourceFinish {
254250
std::string requestId;
255251
HighResTimeStamp start;
252+
int encodedDataLength;
253+
int decodedBodyLength;
256254
ThreadId threadId;
257255
HighResTimeStamp createdAt = HighResTimeStamp::now();
258256
};
@@ -265,6 +263,7 @@ class PerformanceTracer {
265263
std::string mimeType;
266264
std::string protocol;
267265
int statusCode;
266+
folly::dynamic timing;
268267
ThreadId threadId;
269268
HighResTimeStamp createdAt = HighResTimeStamp::now();
270269
};
@@ -275,7 +274,6 @@ class PerformanceTracer {
275274
PerformanceTracerEventEventLoopMicrotask,
276275
PerformanceTracerEventMark,
277276
PerformanceTracerEventMeasure,
278-
PerformanceTracerResourceWillSendRequest,
279277
PerformanceTracerResourceSendRequest,
280278
PerformanceTracerResourceReceiveResponse,
281279
PerformanceTracerResourceFinish>;

packages/react-native/ReactCommon/react/networking/NetworkReporter.cpp

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,16 @@ void NetworkReporter::reportRequestStart(
3838
const std::optional<ResponseInfo>& redirectResponse) {
3939
auto now = HighResTimeStamp::now();
4040

41-
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
42-
// All builds: Annotate PerformanceResourceTiming metadata
43-
{
44-
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
45-
perfTimingsBuffer_.emplace(
46-
requestId,
47-
ResourceTimingData{
48-
.url = requestInfo.url,
49-
.fetchStart = now,
50-
.requestStart = now,
51-
});
52-
}
41+
// All builds: Annotate PerformanceResourceTiming metadata
42+
{
43+
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
44+
perfTimingsBuffer_.emplace(
45+
requestId,
46+
ResourceTimingData{
47+
.url = requestInfo.url,
48+
.fetchStart = now,
49+
.requestStart = now,
50+
});
5351
}
5452

5553
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
@@ -76,7 +74,6 @@ void NetworkReporter::reportRequestStart(
7674
// Debugger enabled: Add trace events to Performance timeline
7775
auto& performanceTracer =
7876
jsinspector_modern::tracing::PerformanceTracer::getInstance();
79-
performanceTracer.reportResourceWillSendRequest(requestId, now);
8077
performanceTracer.reportResourceSendRequest(
8178
requestId, now, requestInfo.url, requestInfo.httpMethod, headers);
8279
#endif
@@ -87,14 +84,12 @@ void NetworkReporter::reportConnectionTiming(
8784
const std::optional<Headers>& headers) {
8885
auto now = HighResTimeStamp::now();
8986

90-
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
91-
// All builds: Annotate PerformanceResourceTiming metadata
92-
{
93-
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
94-
auto it = perfTimingsBuffer_.find(requestId);
95-
if (it != perfTimingsBuffer_.end()) {
96-
it->second.connectStart = now;
97-
}
87+
// All builds: Annotate PerformanceResourceTiming metadata
88+
{
89+
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
90+
auto it = perfTimingsBuffer_.find(requestId);
91+
if (it != perfTimingsBuffer_.end()) {
92+
it->second.connectStart = now;
9893
}
9994
}
10095

@@ -112,20 +107,18 @@ void NetworkReporter::reportResponseStart(
112107
auto now = HighResTimeStamp::now();
113108
auto headers = responseInfo.headers.value_or(Headers{});
114109

115-
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
116-
// All builds: Annotate PerformanceResourceTiming metadata
117-
{
118-
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
119-
auto it = perfTimingsBuffer_.find(requestId);
120-
if (it != perfTimingsBuffer_.end()) {
121-
auto contentType = jsinspector_modern::mimeTypeFromHeaders(headers);
122-
it->second.connectEnd = now;
123-
it->second.responseStart = now;
124-
it->second.responseStatus = responseInfo.statusCode;
125-
it->second.contentType = contentType;
126-
it->second.encodedBodySize = encodedDataLength;
127-
it->second.decodedBodySize = encodedDataLength;
128-
}
110+
// All builds: Annotate PerformanceResourceTiming metadata
111+
{
112+
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
113+
auto it = perfTimingsBuffer_.find(requestId);
114+
if (it != perfTimingsBuffer_.end()) {
115+
auto contentType = jsinspector_modern::mimeTypeFromHeaders(headers);
116+
it->second.connectEnd = now;
117+
it->second.responseStart = now;
118+
it->second.responseStatus = responseInfo.statusCode;
119+
it->second.contentType = contentType;
120+
it->second.encodedBodySize = encodedDataLength;
121+
it->second.decodedBodySize = encodedDataLength;
129122
}
130123
}
131124

@@ -140,9 +133,34 @@ void NetworkReporter::reportResponseStart(
140133
encodedDataLength));
141134

142135
// Debugger enabled: Add trace event to Performance timeline
143-
jsinspector_modern::tracing::PerformanceTracer::getInstance()
144-
.reportResourceReceiveResponse(
145-
requestId, now, responseInfo.statusCode, headers, encodedDataLength);
136+
{
137+
folly::dynamic timingData = folly::dynamic::object();
138+
139+
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
140+
auto it = perfTimingsBuffer_.find(requestId);
141+
if (it != perfTimingsBuffer_.end()) {
142+
// TODO(T238364329): All relative values in timingData should be based on
143+
// fetchStart, once implemented.
144+
auto requestStart = it->second.requestStart;
145+
timingData["requestTime"] = requestStart.toDOMHighResTimeStamp() / 1000;
146+
timingData["sendStart"] = 0;
147+
timingData["sendEnd"] =
148+
(*it->second.connectStart - requestStart).toDOMHighResTimeStamp();
149+
timingData["receiveHeadersStart"] =
150+
(*it->second.connectStart - requestStart).toDOMHighResTimeStamp();
151+
timingData["receiveHeadersEnd"] =
152+
(now - requestStart).toDOMHighResTimeStamp();
153+
}
154+
155+
jsinspector_modern::tracing::PerformanceTracer::getInstance()
156+
.reportResourceReceiveResponse(
157+
requestId,
158+
now,
159+
responseInfo.statusCode,
160+
headers,
161+
encodedDataLength,
162+
std::move(timingData));
163+
}
146164
#endif
147165
}
148166

@@ -192,8 +210,20 @@ void NetworkReporter::reportResponseEnd(
192210
requestId, encodedDataLength);
193211

194212
// Debugger enabled: Add trace event to Performance timeline
195-
jsinspector_modern::tracing::PerformanceTracer::getInstance()
196-
.reportResourceFinish(requestId, now);
213+
{
214+
int decodedBodyLength = 0;
215+
216+
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
217+
auto it = perfTimingsBuffer_.find(requestId);
218+
if (it != perfTimingsBuffer_.end() &&
219+
it->second.contentType.starts_with("image/")) {
220+
decodedBodyLength = it->second.decodedBodySize;
221+
}
222+
223+
jsinspector_modern::tracing::PerformanceTracer::getInstance()
224+
.reportResourceFinish(
225+
requestId, now, encodedDataLength, decodedBodyLength);
226+
}
197227
#endif
198228
}
199229

0 commit comments

Comments
 (0)