Skip to content
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

Display nested exceptions on the debug view #32410

Merged
merged 1 commit into from
Jul 20, 2018

Conversation

yuki24
Copy link
Contributor

@yuki24 yuki24 commented Apr 2, 2018

This PR adds the ability to show nested exceptions, which I proposed a few weeks ago on the core mailing list.

It's probably easier to understand when you actually see it in action rather than explaining the entire thing, so here comes a screenshot:

out

I'm going to add the same functionality to the plain text response once this is merged.

@rails-bot
Copy link

r? @georgeclaghorn

(@rails-bot has picked a reviewer for you, use r? to override)

Copy link
Contributor

@kaspth kaspth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like the idea of this. But how common are exception causes in development?

end

def source_to_show_id
(traces[trace_to_show].first || {})[:id]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hash(traces[trace_to_show].first)[:id]?

Copy link
Contributor Author

@yuki24 yuki24 Apr 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible, but I couldn't come up with strong advantages over (... || {}) (very basic syntax that beginners can understand while Hash(...) is a method call that could be overridden)

<div id="<%= cause.object_id %>" style="display: none;">
<% wrapper = ActionDispatch::ExceptionWrapper.new(@request.get_header("action_dispatch.backtrace_cleaner"), cause) %>
<%= render "rescues/source", source_extracts: wrapper.source_extracts, show_source_idx: wrapper.source_to_show_id, error_index: index %>
<%= render "rescues/trace", traces: wrapper.traces, trace_to_show: wrapper.trace_to_show, error_index: index %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just pass in a wrapper here and in this template? I'm not liking the wrapper instantiation in here.

Perhaps then we could do

@wrapper.wrapped_causes.each do |cause_wrapper|
  # …
end

Copy link
Contributor Author

@yuki24 yuki24 Apr 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this too. The Enumerable would also remove the need of manually tracking the index. I'll implement this if we can get agreement with more folks.

</div>
<% index += 1 %>
<% end %>

<%= render template: "rescues/_request_and_response" %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets fix up this render to match the style of the others, while we're here.

Copy link
Contributor Author

@yuki24 yuki24 Apr 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather send a separate PR to not make the diff unnecessarily larger. Consistency doesn't seem critical in this particular case.

<%= render template: "rescues/_source" %>
<%= render template: "rescues/_trace" %>
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx, error_index: 0 %>
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show, error_index: 0 %>
<%= render template: "rescues/_request_and_response" %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

<%= render template: "rescues/_source" %>
<%= render template: "rescues/_trace" %>
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx, error_index: 0 %>
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show, error_index: 0 %>
<%= render template: "rescues/_request_and_response" %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

@@ -1,52 +1,54 @@
<% names = @traces.keys %>
<% names = traces.keys %>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this we could spare the multiple instances for error_index: 0 in the render calls.

<% error_index = local_assigns.fetch(:error_index, 0) %>

@yuki24
Copy link
Contributor Author

yuki24 commented Apr 2, 2018

how common are exception causes in development?

Any exception that originates from a rescue_from block has a cause. Also, almost any network-related exception has a cause when retry or some sort of re-connecting happens in a rescue block.

@yuki24 yuki24 force-pushed the show-cause-on-debug-view-2 branch 2 times, most recently from 2f84af7 to b7af040 Compare April 3, 2018 15:44
@yuki24
Copy link
Contributor Author

yuki24 commented Apr 4, 2018

slightly updated the PR.

end

causes
end
Copy link
Contributor Author

@yuki24 yuki24 Apr 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if there's a better way to convert a linked list to an Enumerable. Open to suggestions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to fiddle around with Enumerator but couldn't really come up with something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? (untested)

def causes_for(exception)
  return enum_for(__method__, exception) unless block_given?
  yield exception while exception = exception.cause
end

def wrapped_causes_for(exception, backtrace_cleaner)
  causes_for(exception).map { |cause| self.class.new(backtrace_cleaner, cause) }
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewd tried it in my console, it works!

@gsamokovarov
Copy link
Contributor

gsamokovarov commented Apr 15, 2018

@yuki24 you may also wanna look into making a change in rails/web-console as it relies on the structure of the error page.

Copy link
Contributor

@kaspth kaspth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is pretty much good to go. @yuki24 can you check what this would mean for web-console?

end

causes
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to fiddle around with Enumerator but couldn't really come up with something.

@yuki24
Copy link
Contributor Author

yuki24 commented Jul 6, 2018

@kaspth I haven't looked into it yet will do so if I could find time this weekend.

@yuki24 yuki24 force-pushed the show-cause-on-debug-view-2 branch 3 times, most recently from e9a84f7 to fb6f6dd Compare July 8, 2018 22:06
@yuki24
Copy link
Contributor Author

yuki24 commented Jul 9, 2018

@gsamokovarov @kaspth here is a proof-of-concept branch: rails/web-console@master...yuki24:support-for-nested-exceptions

The current web-conole only points to the last exception. It'd have to be able to switch the exception to look at so it could properly switch the the binding. There's no test yet, but you should be able to see how it works and also how much of complexity needs to be added for nested exception support.

@kaspth
Copy link
Contributor

kaspth commented Jul 15, 2018

@yuki24 that branch looks doable to me 😊 — for this PR have you tried @matthewd's wrapped causes suggestion yet? 😉

@gsamokovarov how does that seem to you? I'd like to move forward with this in the meantime 😊

@gsamokovarov
Copy link
Contributor

@kaspth, please do. @yuki24 I have a few comments about the code structure, but feel free to open the PR and we'll work it out on the rails/web-console side.

@yuki24
Copy link
Contributor Author

yuki24 commented Jul 16, 2018

@kaspth yes, I like @matthewd's idea. I'll update the PR to use it.

@gsamokovarov I'll send a PR shortly.


def wrapped_causes_for(exception, backtrace_cleaner)
causes_for(exception).map { |cause| self.class.new(backtrace_cleaner, cause) }
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Man, this looks clean now 😍

@kaspth kaspth merged commit ba78b1f into rails:master Jul 20, 2018
@kaspth
Copy link
Contributor

kaspth commented Jul 20, 2018

Well done, thanks! 👏

@yuki24 yuki24 deleted the show-cause-on-debug-view-2 branch July 20, 2018 21:48
@yuki24 yuki24 changed the title Show nested exceptions on the debug view Display nested exceptions on the debug view Oct 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants