From 1ed264bc60f3c76ba7fab339806fa1757702a46b Mon Sep 17 00:00:00 2001 From: Ryan Dao Date: Wed, 30 Jul 2014 15:35:47 +0700 Subject: Retrieve source code for the entire stack trace Provide the ability to extract the source code of the entire exception stack trace, not just the frame raising the error. This improves debugging capability of the error page, especially for framework-related errors. --- .../action_dispatch/middleware/debug_exceptions.rb | 35 +++++++++++++++-- .../middleware/exception_wrapper.rb | 17 +++++---- .../middleware/templates/rescues/_source.erb | 40 +++++++++++--------- .../middleware/templates/rescues/_trace.html.erb | 44 ++++++++++++++++++---- .../middleware/templates/rescues/_trace.text.erb | 10 +---- .../middleware/templates/rescues/layout.erb | 6 +++ .../templates/rescues/template_error.html.erb | 25 +----------- .../templates/rescues/template_error.text.erb | 1 - 8 files changed, 109 insertions(+), 69 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index 0ca1a87645..274f6f2f22 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -38,9 +38,7 @@ module ActionDispatch template = ActionView::Base.new([RESCUES_TEMPLATE_PATH], request: request, exception: wrapper.exception, - application_trace: wrapper.application_trace, - framework_trace: wrapper.framework_trace, - full_trace: wrapper.full_trace, + traces: traces_from_wrapper(wrapper), routes_inspector: routes_inspector(exception), source_extract: wrapper.source_extract, line_number: wrapper.line_number, @@ -95,5 +93,36 @@ module ActionDispatch ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes) end end + + # Augment the exception traces by providing ids for all unique stack frame + def traces_from_wrapper(wrapper) + application_trace = wrapper.application_trace + framework_trace = wrapper.framework_trace + full_trace = wrapper.full_trace + + if application_trace && framework_trace + id_counter = 0 + + application_trace = application_trace.map do |trace| + prev = id_counter + id_counter += 1 + { id: prev, trace: trace } + end + + framework_trace = framework_trace.map do |trace| + prev = id_counter + id_counter += 1 + { id: prev, trace: trace } + end + + full_trace = application_trace + framework_trace + end + + { + "Application Trace" => application_trace, + "Framework Trace" => framework_trace, + "Full Trace" => full_trace + } + end end end diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb index 2326bb043a..b98b553c38 100644 --- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb +++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb @@ -61,12 +61,15 @@ module ActionDispatch end def source_extract - if application_trace && trace = application_trace.first - file, line, _ = trace.split(":") - @file = file - @line_number = line.to_i - source_fragment(@file, @line_number) - end + exception.backtrace.map do |trace| + file, line = trace.split(":") + line_number = line.to_i + { + code: source_fragment(file, line_number), + file: file, + line_number: line_number + } + end if exception.backtrace end private @@ -110,7 +113,7 @@ module ActionDispatch def expand_backtrace @exception.backtrace.unshift( @exception.to_s.split("\n") - ).flatten! + ).flatten! end end end diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb index 38429cb78e..51660a619b 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb @@ -1,25 +1,29 @@ <% if @source_extract %> -
-
- Extracted source (around line #<%= @line_number %>): -
-
- - - +
-
-            <% @source_extract.keys.each do |line_number| %>
+  <% @source_extract.each_with_index do |extract_source, index| %>
+    <% if extract_source[:code] %>
+      
" id="frame-source-<%=index%>"> +
+ Extracted source (around line #<%= extract_source[:line_number] %>): +
+
+ + + + <% end %> + + - -
+
+                  <% extract_source[:code].keys.each do |line_number| %>
 <%= line_number -%>
-            <% end %>
-          
-
-<% @source_extract.each do |line, source| -%>
"><%= source -%>
<% end -%> +<% extract_source[:code].each do |line, source| -%>
"><%= source -%>
<% end -%>
-
-
+
+
+
+ <% end %> + <% end %> <% end %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb index b181909bff..f62caf51d7 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb @@ -1,9 +1,4 @@ -<% - traces = { "Application Trace" => @application_trace, - "Framework Trace" => @framework_trace, - "Full Trace" => @full_trace } - names = traces.keys -%> +<% names = @traces.keys %>

Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %>

@@ -16,9 +11,42 @@ <%= name %> <%= '|' unless names.last == name %> <% end %> - <% traces.each do |name, trace| %> + <% @traces.each do |name, trace| %>
;"> -
<%= trace.join "\n" %>
+
<% trace.each do |frame| %><%= frame[:trace] %>
<% end %>
<% end %> + + diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb index d4af5c9b06..36b01bf952 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb @@ -1,15 +1,9 @@ -<% - traces = { "Application Trace" => @application_trace, - "Framework Trace" => @framework_trace, - "Full Trace" => @full_trace } -%> - Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %> -<% traces.each do |name, trace| %> +<% @traces.each do |name, trace| %> <% if trace.any? %> <%= name %> -<%= trace.join("\n") %> +<%= trace.map(&:trace).join("\n") %> <% end %> <% end %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb index bc5d03dc10..e0509f56f4 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb @@ -116,9 +116,15 @@ background-color: #FFCCCC; } + .hidden { + display: none; + } + a { color: #980905; } a:visited { color: #666; } + a.trace-frames { color: #666; } a:hover { color: #C52F24; } + a.trace-frames.selected { color: #C52F24 } <%= yield :style %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb index 027a0f5b3e..c1e8b6cae3 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb @@ -1,4 +1,3 @@ -<% @source_extract = @exception.source_extract(0, :html) %>

<%= @exception.original_exception.class.to_s %> in @@ -12,29 +11,7 @@

<%= h @exception.message %>
-
-
-

Extracted source (around line #<%= @exception.line_number %>):

-
-
- - - - - -
-
-            <% @source_extract.keys.each do |line_number| %>
-<%= line_number -%>
-            <% end %>
-          
-
-
-<% @source_extract.each do |line, source| -%>
"><%= source -%>
<% end -%> -
-
-
-
+ <%= render template: "rescues/_source" %>

<%= @exception.sub_template_message %>

diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb index 5da21d9784..77bcd26726 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb @@ -1,4 +1,3 @@ -<% @source_extract = @exception.source_extract(0, :html) %> <%= @exception.original_exception.class.to_s %> in <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %> Showing <%= @exception.file_name %> where line #<%= @exception.line_number %> raised: -- cgit v1.2.3 From 28595e01283b5c14f20929e782c1fca52ea7a0cc Mon Sep 17 00:00:00 2001 From: Ryan Dao Date: Wed, 30 Jul 2014 21:54:03 +0700 Subject: Update actionpack CHANGELOG --- actionpack/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index c30217b8fe..44b8fa843d 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,8 @@ +* Extract source code for the entire exception stack trace for + better debugging and diagnosis. + + *Ryan Dao* + * Allows ActionDispatch::Request::LOCALHOST to match any IPv4 127.0.0.0/8 loopback address. -- cgit v1.2.3