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

fix: properly normalize erlang errors before emitting telemetry and logging crash_reason #455

Merged
merged 2 commits into from
Jan 14, 2025

Conversation

grzuy
Copy link
Contributor

@grzuy grzuy commented Jan 13, 2025

@grzuy grzuy changed the title fix: logs normalized erlang error when unwrapping Plug.Conn.WrapperError fix: logs normalized erlang error when unwrapping Plug.Conn.WrapperError Jan 13, 2025
assert msg =~ "** (RuntimeError) boom"
assert msg =~ "** (MatchError)"
Copy link
Owner

Choose a reason for hiding this comment

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

What's the reason for this change? Is there an issue that comes up with MatchError that doesn't with a simple raise?

Copy link
Contributor Author

@grzuy grzuy Jan 14, 2025

Choose a reason for hiding this comment

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

Is there an issue that comes up with MatchError that doesn't with a simple raise?

Yes, sorry for the lack of explanation.

Elixir's raise directly errors with an elixir's RuntimeError struct.

However, :one = :two or 1 / 0 will exit with {:badmatch, :two} and :badarith respectively, to name a few examples from https://www.erlang.org/doc/system/errors.html#exit-reasons.

Those need to be normalized with Exception.normalize somewhere, to become well-known elixir Exception structs (https://github.com/elixir-lang/elixir/blob/8deaaf4117fef24f516c12dc40989b9772a6d763/lib/elixir/lib/exception.ex#L2357-L2494).

The symptom in bandit right now is only that the non-normalized exit appears in crash_reason value.

The reason why is properly appearing normalized in the logged text message is because the existent Exception.format before Logger.error in

Logger.error(Exception.format(kind, reason, stacktrace), logger_metadata)
, which does the normalization behind the scenes: https://github.com/elixir-lang/elixir/blob/8deaaf4117fef24f516c12dc40989b9772a6d763/lib/elixir/lib/exception.ex#L134-L137.

Copy link
Owner

Choose a reason for hiding this comment

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

I see. I wonder if we should be doing that for all errors (ie continue to have the Plug.Conn.WrapperError pattern match be 'dumb' and just pass the value through unchanged) and normalize in the other handle_error clauses. Does that make sense, or is it only needed in the narrow case of wrapped errors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think you're right.
That's regardless of whether it's wrapped or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also now realized this will fix/normalize the emitted telemetry exception.

Updated PR title.

@grzuy grzuy changed the title fix: logs normalized erlang error when unwrapping Plug.Conn.WrapperError fix: properly normalize erlang errors before emitting telemetry and logged crash_reason Jan 14, 2025
@mtrudel
Copy link
Owner

mtrudel commented Jan 14, 2025

Looks great! Thanks for the continued work!

@mtrudel mtrudel merged commit 1ddeb34 into mtrudel:main Jan 14, 2025
27 checks passed
@grzuy grzuy deleted the unwrap-normalized branch January 14, 2025 20:04
@grzuy grzuy changed the title fix: properly normalize erlang errors before emitting telemetry and logged crash_reason fix: properly normalize erlang errors before emitting telemetry and logging crash_reason Jan 15, 2025
@mtrudel
Copy link
Owner

mtrudel commented Jan 18, 2025

@grzuy I just noticed that this PR introduced console warnings during tests; would it be sufficient for us to explicitly raise a MatchError / ArithmeticError in the relevant places?

@grzuy
Copy link
Contributor Author

grzuy commented Jan 18, 2025

@grzuy I just noticed that this PR introduced console warnings during tests;

Hey @mtrudel, sorry about that.

#459 should fix one.
Will also fix the other warning soon-ish.

would it be sufficient for us to explicitly raise a MatchError / ArithmeticError in the relevant places?

No, because the test cases are there to test that when original erlang :badarith or {:badmatch, x} are raised, Bandit properly normalizes. If we directly raise the Elixir normalized exception we wouldn't be testing that.

@grzuy
Copy link
Contributor Author

grzuy commented Jan 20, 2025

@mtrudel I think this should fix it #459 🙏

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.

2 participants