From eb947279f08d3394f2de3a5edf4d823becee690c Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Fri, 19 Jan 2024 12:26:15 -0800 Subject: [PATCH] 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 --- .../jsinspector-modern/PageAgent.cpp | 38 ++++++++++++------- .../jsinspector-modern/PageAgent.h | 20 +++++++++- .../jsinspector-modern/PageTarget.cpp | 13 ++++--- .../jsinspector-modern/PageTarget.h | 10 ++++- .../tests/PageTargetTest.cpp | 7 +++- 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp index f6eebbf6296..b39b48729cf 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.cpp @@ -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( - 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( + system_clock::now().time_since_epoch()) + .count())("source", "other")( + "level", "info")("text", text))))); +} + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.h b/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.h index 1bdc5fac4b0..28e1be8bddb 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/PageAgent.h @@ -7,9 +7,13 @@ #pragma once +#include "PageTarget.h" + #include #include + #include +#include 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 diff --git a/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.cpp index fcb5d64427c..b3c1b062553 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.cpp @@ -25,7 +25,9 @@ namespace { */ class PageTargetSession { public: - explicit PageTargetSession(std::unique_ptr remote) + explicit PageTargetSession( + std::unique_ptr remote, + PageTarget::SessionMetadata sessionMetadata) : remote_(std::make_shared(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 PageTarget::connect( - std::unique_ptr connectionToFrontend) { - return std::make_unique( - PageTargetSession(std::move(connectionToFrontend))); + std::unique_ptr connectionToFrontend, + SessionMetadata sessionMetadata) { + return std::make_unique(PageTargetSession( + std::move(connectionToFrontend), std::move(sessionMetadata))); } } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.h index 91ee04f92d9..7e622e79502 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/PageTarget.h @@ -9,6 +9,9 @@ #include +#include +#include + namespace facebook::react::jsinspector_modern { /** @@ -18,6 +21,10 @@ namespace facebook::react::jsinspector_modern { */ class PageTarget { public: + struct SessionMetadata { + std::optional 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 connect( - std::unique_ptr connectionToFrontend); + std::unique_ptr connectionToFrontend, + SessionMetadata sessionMetadata = {}); }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp index cdf8678af8e..07373d7e8e1 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/PageTargetTest.cpp @@ -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,