diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp index 5691ee3ca90..a241f53737b 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp @@ -67,6 +67,21 @@ bool PerformanceTracer::stopTracing() { return false; } + // This is synthetic Trace Event, which should not be represented on a + // timeline. CDT is not using Profile or ProfileChunk events for determining + // trace timeline window, this is why trace that only contains JavaScript + // samples will be displayed as empty. We use this event to avoid that. + // This could happen for non-bridgeless apps, where Performance interface is + // not supported and no spec-compliant Event Loop implementation. + buffer_.push_back(TraceEvent{ + .name = "ReactNative-TracingStopped", + .cat = "disabled-by-default-devtools.timeline", + .ph = 'I', + .ts = getUnixTimestampOfNow(), + .pid = processId_, + .tid = oscompat::getCurrentThreadId(), + }); + performanceMeasureCount_ = 0; profileCount_ = 0; tracing_ = false; @@ -212,6 +227,20 @@ void PerformanceTracer::reportThread(uint64_t id, const std::string& name) { .tid = id, .args = folly::dynamic::object("name", name), }); + + // This is synthetic Trace Event, which should not be represented on a + // timeline. CDT will filter out threads that only have JavaScript samples and + // no timeline events or user timings. We use this event to avoid that. + // This could happen for non-bridgeless apps, where Performance interface is + // not supported and no spec-compliant Event Loop implementation. + buffer_.push_back(TraceEvent{ + .name = "ReactNative-ThreadRegistered", + .cat = "disabled-by-default-devtools.timeline", + .ph = 'I', + .ts = 0, + .pid = processId_, + .tid = id, + }); } uint16_t PerformanceTracer::reportRuntimeProfile(