Add support for replaying logs happen on async server operations#440
Conversation
WalkthroughThe changes in this pull request primarily involve updates to the Changes
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
| keys: | ||
| - v4-package-app-gem-cache-{{ checksum "react_on_rails_pro.gemspec" }} | ||
|
|
||
| # Restore react-on-rails from cache |
There was a problem hiding this comment.
Ignore all changes in this file, it will be reverted after merging the React on Rails part of this PR.
| ruby '3.3.0' | ||
|
|
||
| gem "react_on_rails", "14.0.4" # keep in sync with package.json files | ||
| # gem "react_on_rails", "14.0.4" # keep in sync with package.json files |
There was a problem hiding this comment.
Ignore all changes in this file, it will be reverted after merging the React on Rails part of this PR.
| byebug (~> 11.0) | ||
| pry (>= 0.13, < 0.15) | ||
|
|
||
| PATH |
There was a problem hiding this comment.
Ignore all changes in this file, it will be reverted after merging the React on Rails part of this PR.
| byebug (~> 11.0) | ||
| pry (>= 0.13, < 0.15) | ||
|
|
||
| PATH |
There was a problem hiding this comment.
Ignore all changes in this file, it will be reverted after merging the React on Rails part of this PR.
| "react-dom": "^18.2.0", | ||
| "react-helmet": "^6.0.0-beta.2", | ||
| "react-on-rails": "14.0.4", | ||
| "react-on-rails": "link:.yalc/react-on-rails", |
There was a problem hiding this comment.
Ignore all changes in this file, it will be reverted after merging the React on Rails part of this PR.
| integrity sha512-/uyC7X5NAJV29Nwr9nVKnmNcWo2yire/PPeWbelZ7gjmgnmJJyykL16OZeDfs8IUMIIbpwPIBkno/1hP7ksTIA== | ||
| dependencies: | ||
| "@babel/runtime-corejs3" "^7.12.5" | ||
| "react-on-rails@link:.yalc/react-on-rails": |
There was a problem hiding this comment.
Ignore all changes in this file, it will be reverted after merging the React on Rails part of this PR.
| return vmBundleFilePath; | ||
| } | ||
|
|
||
| function replayVmConsole() { |
There was a problem hiding this comment.
moved to sharedConsoleHistory.ts
Console replay script generation now awaits the render request promise before generating, allowing it to capture console logs from asynchronous operations. The feature of replaying async console logs is implemented in node-renderer in this PR shakacode/react_on_rails_pro#440 * add support for console replay of console logs happen in async operations get console replay messages after promise resolves or rejects use isPromise to check if the result is a promise make consoleReplay function accept the list of logs to be added to the script make consoleHistory argument of consoleReplay optional add comments add comments update comment remove FlowFixMe comment * call clear console history from the generated render code * Revert "call clear console history from the generated render code" This reverts commit 2697ef7. * add comment about clearing console history
…ns are replays and not leaked
Summary
This PR introduces support for replaying console logs generated during asynchronous server operations.
Example
Consider the following server-rendered React component (adapted from the SetTimeoutLoggingApp in the dummy app):
Before
Only the first log ('Console log from SetTimeoutLoggingApp.server.jsx') is replayed on the client side. Logs occurring after any async operations (such as promises or timeouts) were not replayed.
After
All log statements, including those inside asynchronous operations, are now replayed on the client side.
Previous Limitation: Why Async Console Logs Were Not Replayed
Solution: How the Issue Is Addressed
This is an example of using
AsyncLocalStorageto separate the local storage of each async operationAsyncLocalStorage Performance Impact
Using AsyncLocalStorage introduces some overhead when creating new async contexts, such as with promises or timeouts. This is particularly noticeable in older Node.js versions (e.g., Node.js 12), where creating async contexts had significant overhead, as detailed in this issue. Starting with Node.js 14, this overhead has been reduced by about 50%.
However, it's important to note that this benchmark focuses on extreme cases (e.g., creating promises without doing significant work). To provide more realistic insight into performance, I conducted the following benchmarks that show minimal impact when using AsyncLocalStorage for various types of workloads:
I/O-Bound Operations Benchmark
Results: The penalty ranges between -5% to +5%, indicating no significant performance impact, with variations likely caused by disk response times.
CPU-Bound Operations Benchmark
Results: The penalty consistently shows 0%, meaning AsyncLocalStorage has no measurable impact on CPU-bound tasks.
Network-Bound Operations Benchmark
Results: The penalty ranges between -5% and +5%, showing no significant performance impact.
Mixed Workload Benchmark
Results: The penalty varies between -3% and +3%, showing negligible impact for mixed workloads.
Result
Across various benchmarks (I/O-bound, CPU-bound, network-bound, and mixed workloads), the use of AsyncLocalStorage exhibits little to no significant performance penalty. These variations are within acceptable limits and are often due to system factors like disk or network response times. Therefore, the benefits of using AsyncLocalStorage in ensuring proper isolation and log replaying for async operations outweigh the minimal performance overhead observed. Also, to ignore the performance problem completely, we can enable this logging feature in development only.
Summary by CodeRabbit
Release Notes
react-on-railsdependency to version15.0.0-alpha.1.