-
-
Notifications
You must be signed in to change notification settings - Fork 633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] create a dashboard for investigating React on Rails SSR performance #1636
[WIP] create a dashboard for investigating React on Rails SSR performance #1636
Conversation
WalkthroughThe recent update introduces a Trace Visualizer into the application, enabling visualization of operations through a Gantt chart. Key changes include implementation of a new controller, view, and routes for the visualizer, along with tracing enhancements within the Changes
Sequence DiagramsTrace Visualization FlowsequenceDiagram
participant User
participant Browser
participant TraceVisualizerController
participant TraceVisualizer::Engine
User->>Browser: Request data visualization
Browser->>TraceVisualizerController: GET /trace_visualizer
TraceVisualizerController->>TraceVisualizer::Engine: Process log data
TraceVisualizer::Engine->>TraceVisualizerController: Return processed data
TraceVisualizerController->>Browser: Render JSON response
Browser->>User: Display Gantt chart
Component Rendering with TracesequenceDiagram
participant Client
participant ReactOnRails
participant RenderHelper
Client->>ReactOnRails: Request render React component
ReactOnRails->>RenderHelper: Call internal_react_component with trace
RenderHelper->>ReactOnRails: Render component with trace
ReactOnRails->>Client: Return rendered component
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 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 as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
Gemfile.lock
is excluded by!**/*.lock
Files selected for processing (10)
- app/controllers/trace_visualizer/trace_visualizer_controller.rb (1 hunks)
- app/views/trace_visualizer/trace_visualizer/index.html.erb (1 hunks)
- config/routes.rb (1 hunks)
- lib/react_on_rails.rb (1 hunks)
- lib/react_on_rails/helper.rb (2 hunks)
- lib/react_on_rails/server_rendering_js_code.rb (1 hunks)
- lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb (3 hunks)
- lib/react_on_rails/utils.rb (1 hunks)
- lib/tasks/trace_visualizer.rake (1 hunks)
- lib/trace_visualizer/engine.rb (1 hunks)
Files not reviewed due to errors (2)
- lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb (no review received)
- lib/react_on_rails/helper.rb (no review received)
Files skipped from review due to trivial changes (2)
- config/routes.rb
- lib/trace_visualizer/engine.rb
Additional comments not posted (1)
lib/react_on_rails.rb (1)
29-29
: Integration of Trace Visualizer engine.The addition of
require 'trace_visualizer/engine'
is correctly placed among otherrequire
statements, ensuring that the Trace Visualizer is loaded with the React on Rails framework. This is crucial for the functionality of the new dashboard.
font-family: Arial, sans-serif; | ||
padding: 20px; | ||
} | ||
.gantt-chart { | ||
width: 100%; | ||
position: relative; | ||
height: auto; | ||
border-left: 2px solid #000; | ||
border-top: 1px solid #000; | ||
} | ||
.task { | ||
position: absolute; | ||
height: 30px; | ||
background-color: #76A5AF; | ||
color: white; | ||
line-height: 30px; | ||
padding-left: 5px; | ||
border-radius: 5px; | ||
border: 1px solid #639; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="chartContainer" class="gantt-chart"></div> | ||
|
||
<script> | ||
window.OPERATIONS_TIMELINE = <%= raw @json_data %> | ||
</script> | ||
|
||
<script> | ||
// Sample JSON data | ||
const operations = window.OPERATIONS_TIMELINE; | ||
|
||
function findMinStartTime(requestData) { | ||
let minStartTime = Infinity; | ||
requestData.operation_stack.forEach(op => { | ||
minStartTime = Math.min(minStartTime, op.start_time); | ||
op.suboperations.forEach(subOp => { | ||
minStartTime = Math.min(minStartTime, subOp.start_time); | ||
}); | ||
}); | ||
return minStartTime; | ||
} | ||
|
||
function renderGanttChart(requestData, requestLevel) { | ||
const minStartTime = findMinStartTime(requestData); | ||
console.log(`MIN Start Time: ${minStartTime}`); | ||
let maxEndTime = 0; | ||
requestData.operation_stack.forEach((op, stackIndex) => { | ||
const startTime = (op.start_time - minStartTime); | ||
const duration = op.duration; | ||
maxEndTime = Math.max(maxEndTime, startTime + duration); | ||
|
||
op.suboperations.forEach(subOp => { | ||
const subStartTime = (subOp.start_time - minStartTime); | ||
const subDuration = subOp.duration; | ||
maxEndTime = Math.max(maxEndTime, subStartTime + subDuration); | ||
}); | ||
}); | ||
|
||
const scale = 1000 / maxEndTime; // Scaling to fit in 1000px width | ||
function renderOperation(op, startTime, top) { | ||
const duration = op.duration * scale; | ||
const task = document.createElement('div'); | ||
task.className = 'task'; | ||
task.style.top = `${top}px`; | ||
task.style.left = `${startTime*1000}px`; | ||
task.style.width = `${duration}px`; | ||
task.textContent = `${op.operation_name} (${op.duration.toFixed(2)} ms)`; | ||
// add tooltip | ||
task.title = `${op.operation_name}-${op.message} (${op.duration.toFixed(2)} ms)`; | ||
chartContainer.appendChild(task); | ||
|
||
let upperLevels = 0; | ||
op.suboperations.forEach((subOp, subIndex) => { | ||
const subStartTime = (subOp.start_time - minStartTime) * scale; | ||
const upperBranchLevel = renderOperation(subOp, subStartTime, top + 40); | ||
upperLevels = upperBranchLevel > upperLevels ? upperBranchLevel : upperLevels; | ||
}); | ||
return upperLevels + 1; | ||
} | ||
|
||
let levels = requestLevel; | ||
requestData.operation_stack.forEach((op) => { | ||
const startTime = (op.start_time - minStartTime) * scale; | ||
levels += renderOperation(op, startTime, levels * 40); // Increment top value for each operation, not suboperation | ||
}); | ||
levels++; | ||
return levels; | ||
} | ||
|
||
let requestLevels = 0; | ||
operations.forEach(requestData => { | ||
const currentRequestLevels = renderGanttChart(requestData, requestLevels) | ||
requestLevels += currentRequestLevels; | ||
}); | ||
chartContainer.height = `${requestLevels * 40 + 80}px` | ||
</script> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comprehensive Review of the Trace Visualizer HTML and JavaScript
The overall structure and implementation of the HTML and JavaScript for the Trace Visualizer is robust and well-organized. The use of inline JavaScript to manipulate DOM elements for dynamic Gantt chart rendering is appropriate given the context of a performance visualization tool. The CSS styling is minimalistic yet effective, ensuring that the visual elements are clear and concise.
However, there are a few areas that could be improved:
- JavaScript Modularity: The JavaScript code is embedded directly within the HTML document. For better maintainability and scalability, consider extracting this into separate JavaScript files. This not only cleans up the HTML file but also allows for easier testing and reusability of the JavaScript code.
- Error Handling in JavaScript: While the script handles the basic flow well, adding error handling around JSON parsing and DOM manipulations could prevent runtime errors and improve the robustness of the page.
- Accessibility: Ensure that the dynamically generated DOM elements (tasks in the Gantt chart) are accessible. This includes proper roles, labels, and keyboard navigability.
- Performance Considerations: For large datasets, the current implementation might become slow as it involves multiple nested loops and DOM manipulations. Consider optimizing the rendering logic or using a virtual DOM approach to handle larger datasets efficiently.
Overall, the implementation meets the basic requirements but could be enhanced by addressing the above points.
namespace :react_on_rails do | ||
task trace_visualizer: :environment do | ||
require 'rack/handler/puma' # Using Puma as the server | ||
Rack::Handler::Puma.run TraceVisualizer::Engine, Port: 5200 do |server| | ||
puts 'Serving Trace Visualizer on http://localhost:5200' | ||
trap(:INT) do | ||
server.stop | ||
puts 'Shutting down server' | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper server shutdown handling.
While the task correctly sets up the server and handles SIGINT for a graceful shutdown, consider also handling SIGTERM for unexpected terminations. This ensures that the server shuts down gracefully in more scenarios.
+ trap(:TERM) do
+ server.stop
+ puts 'Shutting down server due to SIGTERM'
+ end
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
namespace :react_on_rails do | |
task trace_visualizer: :environment do | |
require 'rack/handler/puma' # Using Puma as the server | |
Rack::Handler::Puma.run TraceVisualizer::Engine, Port: 5200 do |server| | |
puts 'Serving Trace Visualizer on http://localhost:5200' | |
trap(:INT) do | |
server.stop | |
puts 'Shutting down server' | |
end | |
end | |
end | |
namespace :react_on_rails do | |
task trace_visualizer: :environment do | |
require 'rack/handler/puma' # Using Puma as the server | |
Rack::Handler::Puma.run TraceVisualizer::Engine, Port: 5200 do |server| | |
puts 'Serving Trace Visualizer on http://localhost:5200' | |
trap(:INT) do | |
server.stop | |
puts 'Shutting down server' | |
end | |
trap(:TERM) do | |
server.stop | |
puts 'Shutting down server due to SIGTERM' | |
end | |
end | |
end |
ReactOnRails::Utils.with_trace(react_component_name) do | ||
config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file | ||
|
||
config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file | ||
if render_options.prerender == true && config_server_bundle_js.blank? | ||
msg = <<~MSG | ||
The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration | ||
for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`. | ||
Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering. | ||
Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/ | ||
MSG | ||
raise ReactOnRails::Error, msg | ||
end | ||
|
||
if render_options.prerender == true && config_server_bundle_js.blank? | ||
msg = <<~MSG | ||
The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration | ||
for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`. | ||
Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering. | ||
Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/ | ||
MSG | ||
raise ReactOnRails::Error, msg | ||
js_code_renderer.render(props_string, rails_context, redux_stores, react_component_name, render_options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor tracing and error handling in server-side rendering.
The addition of tracing within the server_rendering_component_js_code
method enhances debugging capabilities. However, the error message could be made more user-friendly and actionable.
- Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/
+ Please check the configuration or visit https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/ for more information.
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
ReactOnRails::Utils.with_trace(react_component_name) do | |
config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file | |
config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file | |
if render_options.prerender == true && config_server_bundle_js.blank? | |
msg = <<~MSG | |
The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration | |
for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`. | |
Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering. | |
Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/ | |
MSG | |
raise ReactOnRails::Error, msg | |
end | |
if render_options.prerender == true && config_server_bundle_js.blank? | |
msg = <<~MSG | |
The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration | |
for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`. | |
Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering. | |
Read more at https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/ | |
MSG | |
raise ReactOnRails::Error, msg | |
js_code_renderer.render(props_string, rails_context, redux_stores, react_component_name, render_options) | |
ReactOnRails::Utils.with_trace(react_component_name) do | |
config_server_bundle_js = ReactOnRails.configuration.server_bundle_js_file | |
if render_options.prerender == true && config_server_bundle_js.blank? | |
msg = <<~MSG | |
The `prerender` option to allow Server Side Rendering is marked as true but the ReactOnRails configuration | |
for `server_bundle_js_file` is nil or not present in `config/initializers/react_on_rails.rb`. | |
Set `config.server_bundle_js_file` to your javascript bundle to allow server side rendering. | |
Please check the configuration or visit https://www.shakacode.com/react-on-rails/docs/guides/react-server-rendering/ for more information. | |
MSG | |
raise ReactOnRails::Error, msg | |
end | |
js_code_renderer.render(props_string, rails_context, redux_stores, react_component_name, render_options) |
def index | ||
log_file_path = "./log1.log" | ||
log_file_content = File.read(log_file_path) | ||
|
||
map_request_id_to_path = {} | ||
map_request_id_to_operation_stack = {} | ||
|
||
log_file_content.each_line do |line| | ||
# get lines like this: | ||
# [04b9a1be-1312-4053-9598-f500a81f0203] Started GET "/server_side_hello_world_hooks" for ::1 at 2024-06-24 12:27:08 +0300 | ||
# it is a request start line. | ||
# Request id is between square brackets, request method is after "Started", request path is in quotes after method name. | ||
if line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] Started (\w+) "(.*)" for/ | ||
request_id = ::Regexp.last_match(1) | ||
path = ::Regexp.last_match(3) | ||
map_request_id_to_path[request_id] = path | ||
map_request_id_to_operation_stack[request_id] = [] | ||
end | ||
|
||
# Each operation logs the following line to logs | ||
# [04b9a1be-1312-4053-9598-f500a81f0203] [ReactOnRailsPro] [operation-start] PID:49996 server_rendering_component_js_code: HelloWorldHooks, 171923395.5230 | ||
# where last number is the timestamp of the operation start | ||
# After finishing the operation it logs the following line | ||
# [04b9a1be-1312-4053-9598-f500a81f0203] [ReactOnRailsPro] PID:49996 server_rendering_component_js_code: HelloWorldHooks, 2.1ms | ||
# We need to extract the request id, operation name and duration of the operation | ||
# Also, we need to extract suboperations | ||
if line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] \[ReactOnRails\] \[operation-start\] PID:\d+ (\w+): (.*), (\d+\.\d+)/ | ||
request_id = ::Regexp.last_match(1) | ||
operation_name = ::Regexp.last_match(2) | ||
message = ::Regexp.last_match(3) | ||
start_time = ::Regexp.last_match(4).to_f | ||
map_request_id_to_operation_stack[request_id] << { | ||
operation_name: operation_name, | ||
message: message, | ||
suboperations: [], | ||
start_time: start_time, | ||
} | ||
end | ||
|
||
next unless line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] \[ReactOnRails\] PID:\d+ (\w+): (.*), (\d+\.\d+)ms/ | ||
|
||
# binding.pry | ||
request_id = ::Regexp.last_match(1) | ||
operation_name = ::Regexp.last_match(2) | ||
message = ::Regexp.last_match(3) | ||
duration = ::Regexp.last_match(4).to_f | ||
current_operation_in_stack = map_request_id_to_operation_stack[request_id].last | ||
|
||
if current_operation_in_stack[:operation_name] != operation_name || current_operation_in_stack[:message] != message | ||
raise "Unmatched operation name" | ||
end | ||
|
||
current_operation_in_stack[:duration] = duration | ||
if map_request_id_to_operation_stack[request_id].size > 1 | ||
map_request_id_to_operation_stack[request_id].pop | ||
map_request_id_to_operation_stack[request_id].last[:suboperations] << current_operation_in_stack | ||
end | ||
end | ||
|
||
# render map_request_id_to_operation_stack to json | ||
# replace request ids with paths | ||
@json_data = map_request_id_to_operation_stack.map do |request_id, operation_stack| | ||
path = map_request_id_to_path[request_id] | ||
{ path: path, operation_stack: operation_stack } | ||
end | ||
@json_data = @json_data.to_json | ||
|
||
# render the view in app/views/trace_visualizer/trace_visualizer/index.html.erb | ||
# with the json data | ||
render "index" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimize log file processing and error handling.
The index
method effectively parses log files and maps operations. Consider handling potential errors such as file not found or unreadable logs to enhance robustness.
+ if !File.exist?(log_file_path)
+ raise "Log file not found at #{log_file_path}"
+ end
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
def index | |
log_file_path = "./log1.log" | |
log_file_content = File.read(log_file_path) | |
map_request_id_to_path = {} | |
map_request_id_to_operation_stack = {} | |
log_file_content.each_line do |line| | |
# get lines like this: | |
# [04b9a1be-1312-4053-9598-f500a81f0203] Started GET "/server_side_hello_world_hooks" for ::1 at 2024-06-24 12:27:08 +0300 | |
# it is a request start line. | |
# Request id is between square brackets, request method is after "Started", request path is in quotes after method name. | |
if line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] Started (\w+) "(.*)" for/ | |
request_id = ::Regexp.last_match(1) | |
path = ::Regexp.last_match(3) | |
map_request_id_to_path[request_id] = path | |
map_request_id_to_operation_stack[request_id] = [] | |
end | |
# Each operation logs the following line to logs | |
# [04b9a1be-1312-4053-9598-f500a81f0203] [ReactOnRailsPro] [operation-start] PID:49996 server_rendering_component_js_code: HelloWorldHooks, 171923395.5230 | |
# where last number is the timestamp of the operation start | |
# After finishing the operation it logs the following line | |
# [04b9a1be-1312-4053-9598-f500a81f0203] [ReactOnRailsPro] PID:49996 server_rendering_component_js_code: HelloWorldHooks, 2.1ms | |
# We need to extract the request id, operation name and duration of the operation | |
# Also, we need to extract suboperations | |
if line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] \[ReactOnRails\] \[operation-start\] PID:\d+ (\w+): (.*), (\d+\.\d+)/ | |
request_id = ::Regexp.last_match(1) | |
operation_name = ::Regexp.last_match(2) | |
message = ::Regexp.last_match(3) | |
start_time = ::Regexp.last_match(4).to_f | |
map_request_id_to_operation_stack[request_id] << { | |
operation_name: operation_name, | |
message: message, | |
suboperations: [], | |
start_time: start_time, | |
} | |
end | |
next unless line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] \[ReactOnRails\] PID:\d+ (\w+): (.*), (\d+\.\d+)ms/ | |
# binding.pry | |
request_id = ::Regexp.last_match(1) | |
operation_name = ::Regexp.last_match(2) | |
message = ::Regexp.last_match(3) | |
duration = ::Regexp.last_match(4).to_f | |
current_operation_in_stack = map_request_id_to_operation_stack[request_id].last | |
if current_operation_in_stack[:operation_name] != operation_name || current_operation_in_stack[:message] != message | |
raise "Unmatched operation name" | |
end | |
current_operation_in_stack[:duration] = duration | |
if map_request_id_to_operation_stack[request_id].size > 1 | |
map_request_id_to_operation_stack[request_id].pop | |
map_request_id_to_operation_stack[request_id].last[:suboperations] << current_operation_in_stack | |
end | |
end | |
# render map_request_id_to_operation_stack to json | |
# replace request ids with paths | |
@json_data = map_request_id_to_operation_stack.map do |request_id, operation_stack| | |
path = map_request_id_to_path[request_id] | |
{ path: path, operation_stack: operation_stack } | |
end | |
@json_data = @json_data.to_json | |
# render the view in app/views/trace_visualizer/trace_visualizer/index.html.erb | |
# with the json data | |
render "index" | |
end | |
def index | |
log_file_path = "./log1.log" | |
if !File.exist?(log_file_path) | |
raise "Log file not found at #{log_file_path}" | |
end | |
log_file_content = File.read(log_file_path) | |
map_request_id_to_path = {} | |
map_request_id_to_operation_stack = {} | |
log_file_content.each_line do |line| | |
# get lines like this: | |
# [04b9a1be-1312-4053-9598-f500a81f0203] Started GET "/server_side_hello_world_hooks" for ::1 at 2024-06-24 12:27:08 +0300 | |
# it is a request start line. | |
# Request id is between square brackets, request method is after "Started", request path is in quotes after method name. | |
if line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] Started (\w+) "(.*)" for/ | |
request_id = ::Regexp.last_match(1) | |
path = ::Regexp.last_match(3) | |
map_request_id_to_path[request_id] = path | |
map_request_id_to_operation_stack[request_id] = [] | |
end | |
# Each operation logs the following line to logs | |
# [04b9a1be-1312-4053-9598-f500a81f0203] [ReactOnRailsPro] [operation-start] PID:49996 server_rendering_component_js_code: HelloWorldHooks, 171923395.5230 | |
# where last number is the timestamp of the operation start | |
# After finishing the operation it logs the following line | |
# [04b9a1be-1312-4053-9598-f500a81f0203] [ReactOnRailsPro] PID:49996 server_rendering_component_js_code: HelloWorldHooks, 2.1ms | |
# We need to extract the request id, operation name and duration of the operation | |
# Also, we need to extract suboperations | |
if line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] \[ReactOnRails\] \[operation-start\] PID:\d+ (\w+): (.*), (\d+\.\d+)/ | |
request_id = ::Regexp.last_match(1) | |
operation_name = ::Regexp.last_match(2) | |
message = ::Regexp.last_match(3) | |
start_time = ::Regexp.last_match(4).to_f | |
map_request_id_to_operation_stack[request_id] << { | |
operation_name: operation_name, | |
message: message, | |
suboperations: [], | |
start_time: start_time, | |
} | |
end | |
next unless line =~ /\[(\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\] \[ReactOnRails\] PID:\d+ (\w+): (.*), (\d+\.\d+)ms/ | |
# binding.pry | |
request_id = ::Regexp.last_match(1) | |
operation_name = ::Regexp.last_match(2) | |
message = ::Regexp.last_match(3) | |
duration = ::Regexp.last_match(4).to_f | |
current_operation_in_stack = map_request_id_to_operation_stack[request_id].last | |
if current_operation_in_stack[:operation_name] != operation_name || current_operation_in_stack[:message] != message | |
raise "Unmatched operation name" | |
end | |
current_operation_in_stack[:duration] = duration | |
if map_request_id_to_operation_stack[request_id].size > 1 | |
map_request_id_to_operation_stack[request_id].pop | |
map_request_id_to_operation_stack[request_id].last[:suboperations] << current_operation_in_stack | |
end | |
end | |
# render map_request_id_to_operation_stack to json | |
# replace request ids with paths | |
@json_data = map_request_id_to_operation_stack.map do |request_id, operation_stack| | |
path = map_request_id_to_path[request_id] | |
{ path: path, operation_stack: operation_stack } | |
end | |
@json_data = @json_data.to_json | |
# render the view in app/views/trace_visualizer/trace_visualizer/index.html.erb | |
# with the json data | |
render "index" | |
end |
Summary
Remove this paragraph and provide a general description of the code changes in your pull
request... were there any bugs you had fixed? If so, mention them. If
these bugs have open GitHub issues, be sure to tag them here as well,
to keep the conversation linked together.
Pull Request checklist
Remove this line after checking all the items here. If the item is not applicable to the PR, both check it out and wrap it by
~
.Add the CHANGELOG entry at the top of the file.
Other Information
Remove this paragraph and mention any other important and relevant information such as benchmarks.
This change is
Summary by CodeRabbit
New Features
http://localhost:5200
.Enhancements
Refactor