mirror of https://github.com/rails/rails
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.
This commit is contained in:
parent
30529dc00f
commit
1ed264bc60
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
<% if @source_extract %>
|
||||
<div class="source">
|
||||
<div class="info">
|
||||
Extracted source (around line <strong>#<%= @line_number %></strong>):
|
||||
</div>
|
||||
<div class="data">
|
||||
<table cellpadding="0" cellspacing="0" class="lines">
|
||||
<tr>
|
||||
<td>
|
||||
<pre class="line_numbers">
|
||||
<% @source_extract.keys.each do |line_number| %>
|
||||
<% @source_extract.each_with_index do |extract_source, index| %>
|
||||
<% if extract_source[:code] %>
|
||||
<div class="source <%="hidden" if index != 0%>" id="frame-source-<%=index%>">
|
||||
<div class="info">
|
||||
Extracted source (around line <strong>#<%= extract_source[:line_number] %></strong>):
|
||||
</div>
|
||||
<div class="data">
|
||||
<table cellpadding="0" cellspacing="0" class="lines">
|
||||
<tr>
|
||||
<td>
|
||||
<pre class="line_numbers">
|
||||
<% extract_source[:code].keys.each do |line_number| %>
|
||||
<span><%= line_number -%></span>
|
||||
<% end %>
|
||||
</pre>
|
||||
</td>
|
||||
<% end %>
|
||||
</pre>
|
||||
</td>
|
||||
<td width="100%">
|
||||
<pre>
|
||||
<% @source_extract.each do |line, source| -%><div class="line<%= " active" if line == @line_number -%>"><%= source -%></div><% end -%>
|
||||
<% extract_source[:code].each do |line, source| -%><div class="line<%= " active" if line == extract_source[:line_number] -%>"><%= source -%></div><% end -%>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
<%
|
||||
traces = { "Application Trace" => @application_trace,
|
||||
"Framework Trace" => @framework_trace,
|
||||
"Full Trace" => @full_trace }
|
||||
names = traces.keys
|
||||
%>
|
||||
<% names = @traces.keys %>
|
||||
|
||||
<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p>
|
||||
|
||||
|
@ -16,9 +11,42 @@
|
|||
<a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
|
||||
<% end %>
|
||||
|
||||
<% traces.each do |name, trace| %>
|
||||
<% @traces.each do |name, trace| %>
|
||||
<div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == "Application Trace") ? 'block' : 'none' %>;">
|
||||
<pre><code><%= trace.join "\n" %></code></pre>
|
||||
<pre><code><% trace.each do |frame| %><a class="trace-frames" data-frame-id="<%= frame[:id] %>" href="#"><%= frame[:trace] %></a><br><% end %></code></pre>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
var traceFrames = document.getElementsByClassName('trace-frames');
|
||||
var selectedFrame, currentSource = document.getElementById('frame-source-0');
|
||||
|
||||
// Add click listeners for all stack frames
|
||||
for (var i = 0; i < traceFrames.length; i++) {
|
||||
traceFrames[i].addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
var target = e.target;
|
||||
var frame_id = target.dataset.frameId;
|
||||
|
||||
if (selectedFrame) {
|
||||
selectedFrame.className = selectedFrame.className.replace("selected", "");
|
||||
}
|
||||
|
||||
target.className += " selected";
|
||||
selectedFrame = target;
|
||||
|
||||
// Change the extracted source code
|
||||
changeSourceExtract(frame_id);
|
||||
});
|
||||
|
||||
function changeSourceExtract(frame_id) {
|
||||
var el = document.getElementById('frame-source-' + frame_id);
|
||||
if (currentSource && el) {
|
||||
currentSource.className += " hidden";
|
||||
el.className = el.className.replace(" hidden", "");
|
||||
currentSource = el;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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 %>
|
||||
</style>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<% @source_extract = @exception.source_extract(0, :html) %>
|
||||
<header>
|
||||
<h1>
|
||||
<%= @exception.original_exception.class.to_s %> in
|
||||
|
@ -12,29 +11,7 @@
|
|||
</p>
|
||||
<pre><code><%= h @exception.message %></code></pre>
|
||||
|
||||
<div class="source">
|
||||
<div class="info">
|
||||
<p>Extracted source (around line <strong>#<%= @exception.line_number %></strong>):</p>
|
||||
</div>
|
||||
<div class="data">
|
||||
<table cellpadding="0" cellspacing="0" class="lines">
|
||||
<tr>
|
||||
<td>
|
||||
<pre class="line_numbers">
|
||||
<% @source_extract.keys.each do |line_number| %>
|
||||
<span><%= line_number -%></span>
|
||||
<% end %>
|
||||
</pre>
|
||||
</td>
|
||||
<td width="100%">
|
||||
<pre>
|
||||
<% @source_extract.each do |line, source| -%><div class="line<%= " active" if line == @exception.line_number -%>"><%= source -%></div><% end -%>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<%= render template: "rescues/_source" %>
|
||||
|
||||
<p><%= @exception.sub_template_message %></p>
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue