Inject log with CDP integration name if provided (#42384)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/42384

Changelog: [Internal]

Similar to D52894171, adds a console log message identifying the specific CDP backend integration, based on an optional `SessionMetadata` object passed to `PageTarget::connect()`. This is helpful during development+rollout as we will have 4+ such call sites (iOS/Android, Bridge/Bridgeless).

Reviewed By: huntie

Differential Revision: D52905488

fbshipit-source-id: d26aae1d07c2c42965498a81f03d826de98fa222
This commit is contained in:
Moti Zilberman
2024-01-19 12:26:15 -08:00
committed by Facebook GitHub Bot
parent 2e47770688
commit eb947279f0
5 changed files with 66 additions and 22 deletions
@@ -27,8 +27,11 @@ static constexpr auto kModernCDPBackendNotice =
"NOTE:" ANSI_WEIGHT_RESET " You are using the " ANSI_STYLE_ITALIC
"modern" ANSI_STYLE_RESET " CDP backend for React Native (PageTarget)."sv;
PageAgent::PageAgent(FrontendChannel frontendChannel)
: frontendChannel_(frontendChannel) {}
PageAgent::PageAgent(
FrontendChannel frontendChannel,
PageTarget::SessionMetadata sessionMetadata)
: frontendChannel_(frontendChannel),
sessionMetadata_(std::move(sessionMetadata)) {}
void PageAgent::handleRequest(const cdp::PreparsedRequest& req) {
if (req.method == "Log.enable") {
@@ -37,17 +40,12 @@ void PageAgent::handleRequest(const cdp::PreparsedRequest& req) {
folly::toJson(folly::dynamic::object("id", req.id)("result", nullptr)));
// Send a log entry identifying the modern CDP backend.
frontendChannel_(
folly::toJson(folly::dynamic::object("method", "Log.entryAdded")(
"params",
folly::dynamic::object(
"entry",
folly::dynamic::object(
"timestamp",
duration_cast<milliseconds>(
system_clock::now().time_since_epoch())
.count())("source", "other")(
"level", "info")("text", kModernCDPBackendNotice)))));
sendInfoLogEntry(kModernCDPBackendNotice);
// Send a log entry with the integration name.
if (sessionMetadata_.integrationName) {
sendInfoLogEntry("Integration: " + *sessionMetadata_.integrationName);
}
return;
}
@@ -59,4 +57,18 @@ void PageAgent::handleRequest(const cdp::PreparsedRequest& req) {
frontendChannel_(json);
}
void PageAgent::sendInfoLogEntry(std::string_view text) {
frontendChannel_(
folly::toJson(folly::dynamic::object("method", "Log.entryAdded")(
"params",
folly::dynamic::object(
"entry",
folly::dynamic::object(
"timestamp",
duration_cast<milliseconds>(
system_clock::now().time_since_epoch())
.count())("source", "other")(
"level", "info")("text", text)))));
}
} // namespace facebook::react::jsinspector_modern
@@ -7,9 +7,13 @@
#pragma once
#include "PageTarget.h"
#include <jsinspector-modern/InspectorInterfaces.h>
#include <jsinspector-modern/Parsing.h>
#include <functional>
#include <string_view>
namespace facebook::react::jsinspector_modern {
@@ -25,7 +29,9 @@ class PageAgent {
* \param frontendChannel A channel used to send responses and events to the
* frontend.
*/
explicit PageAgent(FrontendChannel frontendChannel);
PageAgent(
FrontendChannel frontendChannel,
PageTarget::SessionMetadata sessionMetadata);
/**
* Handle a CDP request. The response will be sent over the provided
@@ -35,7 +41,19 @@ class PageAgent {
void handleRequest(const cdp::PreparsedRequest& req);
private:
/**
* Send a simple Log.entryAdded notification with the given
* \param text. You must ensure that the frontend has enabled Log
* notifications (using Log.enable) prior to calling this function. In Chrome
* DevTools, the message will appear in the Console tab along with regular
* console messages. The difference between Log.entryAdded and
* Runtime.consoleAPICalled is that the latter requires an execution context
* ID, which does not exist at the Page level.
*/
void sendInfoLogEntry(std::string_view text);
FrontendChannel frontendChannel_;
const PageTarget::SessionMetadata sessionMetadata_;
};
} // namespace facebook::react::jsinspector_modern
@@ -25,7 +25,9 @@ namespace {
*/
class PageTargetSession {
public:
explicit PageTargetSession(std::unique_ptr<IRemoteConnection> remote)
explicit PageTargetSession(
std::unique_ptr<IRemoteConnection> remote,
PageTarget::SessionMetadata sessionMetadata)
: remote_(std::make_shared<RAIIRemoteConnection>(std::move(remote))),
frontendChannel_(
[remoteWeak = std::weak_ptr(remote_)](std::string_view message) {
@@ -33,7 +35,7 @@ class PageTargetSession {
remote->onMessage(std::string(message));
}
}),
pageAgent_(frontendChannel_) {}
pageAgent_(frontendChannel_, std::move(sessionMetadata)) {}
/**
* Called by CallbackLocalConnection to send a message to this Session's
* Agent.
@@ -77,9 +79,10 @@ class PageTargetSession {
} // namespace
std::unique_ptr<ILocalConnection> PageTarget::connect(
std::unique_ptr<IRemoteConnection> connectionToFrontend) {
return std::make_unique<CallbackLocalConnection>(
PageTargetSession(std::move(connectionToFrontend)));
std::unique_ptr<IRemoteConnection> connectionToFrontend,
SessionMetadata sessionMetadata) {
return std::make_unique<CallbackLocalConnection>(PageTargetSession(
std::move(connectionToFrontend), std::move(sessionMetadata)));
}
} // namespace facebook::react::jsinspector_modern
@@ -9,6 +9,9 @@
#include <jsinspector-modern/InspectorInterfaces.h>
#include <optional>
#include <string>
namespace facebook::react::jsinspector_modern {
/**
@@ -18,6 +21,10 @@ namespace facebook::react::jsinspector_modern {
*/
class PageTarget {
public:
struct SessionMetadata {
std::optional<std::string> integrationName;
};
/**
* Creates a new Session connected to this PageTarget, wrapped in an
* interface which is compatible with \c IInspector::addPage.
@@ -26,7 +33,8 @@ class PageTarget {
* destructor execute.
*/
std::unique_ptr<ILocalConnection> connect(
std::unique_ptr<IRemoteConnection> connectionToFrontend);
std::unique_ptr<IRemoteConnection> connectionToFrontend,
SessionMetadata sessionMetadata = {});
};
} // namespace facebook::react::jsinspector_modern
@@ -31,7 +31,9 @@ namespace {
class PageTargetProtocolTest : public Test {
public:
PageTargetProtocolTest() {
toPage_ = page_.connect(remoteConnections_.make_unique());
toPage_ = page_.connect(
remoteConnections_.make_unique(),
{.integrationName = "PageTargetProtocolTest"});
// In protocol tests, we'll always get an onDisconnect call when we tear
// down the test. Expect it in order to satisfy the strict mock.
@@ -102,7 +104,7 @@ TEST_F(PageTargetProtocolTest, MalformedJson) {
toPage_->sendMessage("{");
}
TEST_F(PageTargetProtocolTest, InjectLogToIdentifyBackend) {
TEST_F(PageTargetProtocolTest, InjectLogsToIdentifyBackend) {
InSequence s;
EXPECT_CALL(fromPage(), onMessage(JsonEq(R"({
@@ -116,6 +118,7 @@ TEST_F(PageTargetProtocolTest, InjectLogToIdentifyBackend) {
onMessage(JsonParsed(AllOf(
AtJsonPtr("/method", "Log.entryAdded"),
AtJsonPtr("/params/entry", Not(IsEmpty()))))))
.Times(2)
.RetiresOnSaturation();
toPage_->sendMessage(R"({
"id": 1,