Skip to content
18 changes: 15 additions & 3 deletions packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class HostAgent::Impl final {
hostMetadata_(std::move(hostMetadata)),
sessionState_(sessionState),
networkIOAgent_(NetworkIOAgent(frontendChannel, std::move(executor))),
tracingAgent_(TracingAgent(frontendChannel, sessionState)) {}
tracingAgent_(
TracingAgent(frontendChannel, sessionState, targetController)) {}

~Impl() {
if (isPausedInDebuggerOverlayVisible_) {
Expand Down Expand Up @@ -310,8 +311,6 @@ class HostAgent::Impl final {
}

void setCurrentInstanceAgent(std::shared_ptr<InstanceAgent> instanceAgent) {
tracingAgent_.setCurrentInstanceAgent(instanceAgent);

auto previousInstanceAgent = std::move(instanceAgent_);
instanceAgent_ = std::move(instanceAgent);

Expand Down Expand Up @@ -462,4 +461,17 @@ void HostAgent::setCurrentInstanceAgent(
impl_->setCurrentInstanceAgent(std::move(instanceAgent));
}

#pragma mark - Tracing

HostTracingAgent::HostTracingAgent(tracing::TraceRecordingState& state)
: tracing::TargetTracingAgent(state) {}

void HostTracingAgent::setTracedInstance(InstanceTarget* instanceTarget) {
if (instanceTarget != nullptr) {
instanceTracingAgent_ = instanceTarget->createTracingAgent(state_);
} else {
instanceTracingAgent_ = nullptr;
}
}

} // namespace facebook::react::jsinspector_modern
22 changes: 22 additions & 0 deletions packages/react-native/ReactCommon/jsinspector-modern/HostAgent.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <jsinspector-modern/InspectorInterfaces.h>
#include <jsinspector-modern/InstanceAgent.h>
#include <jsinspector-modern/cdp/CdpJson.h>
#include <jsinspector-modern/tracing/TargetTracingAgent.h>

namespace facebook::react::jsinspector_modern {

Expand Down Expand Up @@ -75,4 +76,25 @@ class HostAgent final {
std::unique_ptr<Impl> impl_;
};

#pragma mark - Tracing

/**
* An Agent that handles Tracing events for a particular InstanceTarget.
*
* Lifetime of this agent is bound to the lifetime of the Tracing session -
* HostTargetTraceRecording.
*/
class HostTracingAgent : tracing::TargetTracingAgent {
public:
explicit HostTracingAgent(tracing::TraceRecordingState& state);

/**
* Registers the InstanceTarget with this tracing agent.
*/
void setTracedInstance(InstanceTarget* instanceTarget);

private:
std::shared_ptr<InstanceTracingAgent> instanceTracingAgent_{nullptr};
};

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "HostTarget.h"
#include "HostAgent.h"
#include "HostTargetTraceRecording.h"
#include "InspectorInterfaces.h"
#include "InspectorUtilities.h"
#include "InstanceTarget.h"
Expand Down Expand Up @@ -179,6 +180,8 @@ HostTarget::~HostTarget() {
assert(
sessions_.empty() &&
"HostTargetSession objects must be destroyed before their HostTarget. Did you call getInspectorInstance().removePage()?");
// Trace Recording object (traceRecording_) doesn't create an actual session,
// so we don't need to reset it explicitly here.
}

HostTargetDelegate::~HostTargetDelegate() = default;
Expand All @@ -191,6 +194,13 @@ InstanceTarget& HostTarget::registerInstance(InstanceTargetDelegate& delegate) {
[currentInstance = &*currentInstance_](HostTargetSession& session) {
session.setCurrentInstance(currentInstance);
});

if (traceRecording_) {
// Registers the Instance for tracing, if a Trace is currently being
// recorded.
traceRecording_->setTracedInstance(currentInstance_.get());
}

return *currentInstance_;
}

Expand All @@ -200,6 +210,13 @@ void HostTarget::unregisterInstance(InstanceTarget& instance) {
"Invalid unregistration");
sessions_.forEach(
[](HostTargetSession& session) { session.setCurrentInstance(nullptr); });

if (traceRecording_) {
// Unregisters the Instance for tracing, if a Trace is currently being
// recorded.
traceRecording_->setTracedInstance(nullptr);
}

currentInstance_.reset();
}

Expand Down
48 changes: 48 additions & 0 deletions packages/react-native/ReactCommon/jsinspector-modern/HostTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <optional>
#include <string>

#include <jsinspector-modern/tracing/TracingMode.h>

#ifndef JSINSPECTOR_EXPORT
#ifdef _MSC_VER
#ifdef CREATE_SHARED_LIBRARY
Expand All @@ -34,8 +36,10 @@ namespace facebook::react::jsinspector_modern {

class HostTargetSession;
class HostAgent;
class HostTracingAgent;
class HostCommandSender;
class HostTarget;
class HostTargetTraceRecording;

struct HostTargetMetadata {
std::optional<std::string> appDisplayName;
Expand Down Expand Up @@ -166,6 +170,19 @@ class HostTargetController final {
*/
bool decrementPauseOverlayCounter();

/**
* Starts trace recording for this HostTarget.
*
* \param mode In which mode to start the trace recording.
* \return false if already tracing, true otherwise.
*/
bool startTracing(tracing::Mode mode);

/**
* Stops previously started trace recording.
*/
tracing::TraceRecordingState stopTracing();

private:
HostTarget& target_;
size_t pauseOverlayCounter_{0};
Expand Down Expand Up @@ -237,6 +254,29 @@ class JSINSPECTOR_EXPORT HostTarget
*/
void sendCommand(HostCommand command);

/**
* Creates a new HostTracingAgent.
* This Agent is not owned by the HostTarget. The Agent will be destroyed at
* the end of the tracing session.
*
* \param state A reference to the state of the active trace recording.
*/
std::shared_ptr<HostTracingAgent> createTracingAgent(
tracing::TraceRecordingState& state);

/**
* Starts trace recording for this HostTarget.
*
* \param mode In which mode to start the trace recording.
* \return false if already tracing, true otherwise.
*/
bool startTracing(tracing::Mode mode);

/**
* Stops previously started trace recording.
*/
tracing::TraceRecordingState stopTracing();

private:
/**
* Constructs a new HostTarget.
Expand All @@ -257,6 +297,14 @@ class JSINSPECTOR_EXPORT HostTarget
std::shared_ptr<InstanceTarget> currentInstance_{nullptr};
std::unique_ptr<HostCommandSender> commandSender_;

/**
* Current pending trace recording, which encapsulates the configuration of
* the tracing session and the state.
*
* Should only be allocated when there is an active tracing session.
*/
std::unique_ptr<HostTargetTraceRecording> traceRecording_{nullptr};

inline HostTargetDelegate& getDelegate() {
return delegate_;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "HostTargetTraceRecording.h"
#include "HostTarget.h"

namespace facebook::react::jsinspector_modern {

HostTargetTraceRecording::HostTargetTraceRecording(
tracing::Mode tracingMode,
HostTarget& hostTarget)
: tracingMode_(tracingMode), hostTarget_(hostTarget) {}

void HostTargetTraceRecording::setTracedInstance(
InstanceTarget* instanceTarget) {
// If HostTracingAgent is allocated, it means that there is an active tracing
// recording session.
if (hostTracingAgent_ != nullptr) {
hostTracingAgent_->setTracedInstance(instanceTarget);
}
}

void HostTargetTraceRecording::start() {
assert(
hostTracingAgent_ == nullptr &&
"Tracing Agent for the HostTarget was already initialized.");

state_ = tracing::TraceRecordingState{.startTime = HighResTimeStamp::now()};
hostTracingAgent_ = hostTarget_.createTracingAgent(*state_);
}

tracing::TraceRecordingState HostTargetTraceRecording::stop() {
assert(
hostTracingAgent_ != nullptr &&
"TracingAgent for the HostTarget has not been initialized.");
hostTracingAgent_.reset();

assert(
state_.has_value() &&
"The state for this tracing session has not been initialized.");
auto state = std::move(*state_);
state_.reset();

return state;
}

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include "HostAgent.h"
#include "HostTarget.h"
#include "InstanceTarget.h"

#include <jsinspector-modern/tracing/TraceRecordingState.h>

#include <optional>

namespace facebook::react::jsinspector_modern {

/**
* A local representation of the Tracing "session".
*
* Owned by the HostTarget and should only be allocated during an active
* recording.
*
* Owns all allocated Tracing Agents. A single Target can have a single active
* Tracing Agent, but only as a std::weak_ptr.
*/
class HostTargetTraceRecording {
public:
explicit HostTargetTraceRecording(
tracing::Mode tracingMode,
HostTarget& hostTarget);

inline bool isBackgroundInitiated() const {
return tracingMode_ == tracing::Mode::Background;
}

inline bool isUserInitiated() const {
return tracingMode_ == tracing::Mode::CDP;
}

/**
* Updates the current traced Instance for this recording.
*/
void setTracedInstance(InstanceTarget* instanceTarget);

/**
* Starts the recording.
*
* Will allocate all Tracing Agents for all currently registered Targets.
*/
void start();

/**
* Stops the recording and drops the recording state.
*
* Will deallocate all Tracing Agents.
*/
tracing::TraceRecordingState stop();

private:
/**
* The mode in which this trace recording was initialized.
*/
tracing::Mode tracingMode_;

/**
* The Host for which this Trace Recording is going to happen.
*/
HostTarget& hostTarget_;

/**
* The state of the current Trace Recording.
* Only allocated if the recording is enabled.
*/
std::optional<tracing::TraceRecordingState> state_;

/**
* The TracingAgent of the targeted Host.
* Only allocated if the recording is enabled.
*/
std::shared_ptr<HostTracingAgent> hostTracingAgent_;
};

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "HostTarget.h"
#include "HostTargetTraceRecording.h"

namespace facebook::react::jsinspector_modern {

bool HostTargetController::startTracing(tracing::Mode tracingMode) {
return target_.startTracing(tracingMode);
}

tracing::TraceRecordingState HostTargetController::stopTracing() {
return target_.stopTracing();
}

std::shared_ptr<HostTracingAgent> HostTarget::createTracingAgent(
tracing::TraceRecordingState& state) {
auto agent = std::make_shared<HostTracingAgent>(state);
agent->setTracedInstance(currentInstance_.get());
return agent;
}

bool HostTarget::startTracing(tracing::Mode tracingMode) {
if (traceRecording_ != nullptr) {
return false;
}

traceRecording_ =
std::make_unique<HostTargetTraceRecording>(tracingMode, *this);
traceRecording_->setTracedInstance(currentInstance_.get());
traceRecording_->start();

return true;
}

tracing::TraceRecordingState HostTarget::stopTracing() {
assert(traceRecording_ != nullptr && "No tracing in progress");

auto state = traceRecording_->stop();
traceRecording_.reset();

return state;
}

} // namespace facebook::react::jsinspector_modern
Loading
Loading