From 35f2cd26ae06cf44fc0fa99534028edfdfab2ceb Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Wed, 15 Jul 2020 23:28:27 -0700 Subject: [PATCH] Fabric: Introducing `TelemetryController` as part of `MountingManager` Summary: This diff implements TelemetryController, a small tool that can be used to instrument mounting transactions. It abstracts the logic of merging telemetry data of multiple transactions in a thread-safe manner. Changelog: [Internal] Fabric-specific internal change. Reviewed By: sammy-SC Differential Revision: D22490580 fbshipit-source-id: 3f3425b88d38fddb555c1390fd8f1ff3ef1c475a --- .../fabric/mounting/MountingCoordinator.cpp | 7 ++- .../fabric/mounting/MountingCoordinator.h | 5 ++ .../fabric/mounting/TelemetryController.cpp | 58 +++++++++++++++++++ .../fabric/mounting/TelemetryController.h | 58 +++++++++++++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 ReactCommon/fabric/mounting/TelemetryController.cpp create mode 100644 ReactCommon/fabric/mounting/TelemetryController.h diff --git a/ReactCommon/fabric/mounting/MountingCoordinator.cpp b/ReactCommon/fabric/mounting/MountingCoordinator.cpp index d977f35d36b..f4d5f3ab7b8 100644 --- a/ReactCommon/fabric/mounting/MountingCoordinator.cpp +++ b/ReactCommon/fabric/mounting/MountingCoordinator.cpp @@ -24,7 +24,8 @@ MountingCoordinator::MountingCoordinator( std::weak_ptr delegate) : surfaceId_(baseRevision.getRootShadowNode().getSurfaceId()), baseRevision_(baseRevision), - mountingOverrideDelegate_(delegate) { + mountingOverrideDelegate_(delegate), + telemetryController_(*this) { #ifdef RN_SHADOW_TREE_INTROSPECTION stubViewTree_ = stubViewTreeFromShadowNode(baseRevision_.getRootShadowNode()); #endif @@ -172,5 +173,9 @@ better::optional MountingCoordinator::pullTransaction() return transaction; } +TelemetryController const &MountingCoordinator::getTelemetryController() const { + return telemetryController_; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/mounting/MountingCoordinator.h b/ReactCommon/fabric/mounting/MountingCoordinator.h index 556258ef2eb..ed3ffb1a9d3 100644 --- a/ReactCommon/fabric/mounting/MountingCoordinator.h +++ b/ReactCommon/fabric/mounting/MountingCoordinator.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "ShadowTreeRevision.h" #ifdef RN_SHADOW_TREE_INTROSPECTION @@ -69,6 +70,8 @@ class MountingCoordinator final { */ bool waitForTransaction(std::chrono::duration timeout) const; + TelemetryController const &getTelemetryController() const; + /* * Methods from this section are meant to be used by * `MountingOverrideDelegate` only. @@ -104,6 +107,8 @@ class MountingCoordinator final { mutable std::condition_variable signal_; std::weak_ptr mountingOverrideDelegate_; + TelemetryController telemetryController_; + #ifdef RN_SHADOW_TREE_INTROSPECTION void validateTransactionAgainstStubViewTree( ShadowViewMutationList const &mutations, diff --git a/ReactCommon/fabric/mounting/TelemetryController.cpp b/ReactCommon/fabric/mounting/TelemetryController.cpp new file mode 100644 index 00000000000..43c91b5eb85 --- /dev/null +++ b/ReactCommon/fabric/mounting/TelemetryController.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "TelemetryController.h" + +#include + +namespace facebook { +namespace react { + +TelemetryController::TelemetryController( + MountingCoordinator const &mountingCoordinator) noexcept + : mountingCoordinator_(mountingCoordinator) {} + +bool TelemetryController::pullTransaction( + std::function willMount, + std::function doMount, + std::function didMount) const + noexcept { + auto optional = mountingCoordinator_.pullTransaction(); + if (!optional.has_value()) { + return false; + } + + auto transaction = std::move(*optional); + + auto surfaceId = transaction.getSurfaceId(); + auto number = transaction.getNumber(); + auto telemetry = transaction.getTelemetry(); + auto numberOfMutations = transaction.getMutations().size(); + + mutex_.lock(); + auto compoundTelemetry = compoundTelemetry_; + mutex_.unlock(); + + willMount({surfaceId, number, telemetry, compoundTelemetry}); + + telemetry.willMount(); + doMount(std::move(transaction.getMutations())); + telemetry.didMount(); + + compoundTelemetry.incorporate(telemetry, numberOfMutations); + + didMount({surfaceId, number, telemetry, compoundTelemetry}); + + mutex_.lock(); + compoundTelemetry_ = compoundTelemetry; + mutex_.unlock(); + + return true; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/mounting/TelemetryController.h b/ReactCommon/fabric/mounting/TelemetryController.h new file mode 100644 index 00000000000..f5af79c0de0 --- /dev/null +++ b/ReactCommon/fabric/mounting/TelemetryController.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) Facebook, Inc. and its 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 +#include + +#include +#include +#include + +namespace facebook { +namespace react { + +class MountingCoordinator; + +/* + * Provides convenient tools for aggregating and accessing telemetry data + * associated with running Surface. + */ +class TelemetryController final { + friend class MountingCoordinator; + + /* + * To be used by `MountingCoordinator`. + */ + TelemetryController(MountingCoordinator const &mountingCoordinator) noexcept; + + /* + * Not copyable. + */ + TelemetryController(TelemetryController const &other) noexcept = delete; + TelemetryController &operator=(TelemetryController const &other) noexcept = + delete; + + public: + /* + * Calls `MountingCoordinator::pullTransaction()` and aggregates telemetry. + */ + bool pullTransaction( + std::function willMount, + std::function doMount, + std::function didMount) const + noexcept; + + private: + MountingCoordinator const &mountingCoordinator_; + mutable SurfaceTelemetry compoundTelemetry_{}; + mutable std::mutex mutex_; +}; + +} // namespace react +} // namespace facebook