-
Notifications
You must be signed in to change notification settings - Fork 312
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
Optionally log last known call, publish stacktrace in telemetry #366
Optionally log last known call, publish stacktrace in telemetry #366
Conversation
lib/ecto/adapters/sql.ex
Outdated
defp log_stacktrace(nil), do: "" | ||
|
||
defp log_stacktrace(stacktrace) do | ||
{module, function, arity, metadata} = Enum.at(stacktrace, 2) |
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.
@v0idpwn
I'm curious, so I'd like to ask you a question.
Why that can fetch by Enum.at(stacktrace, 2)
?
Stacktrace has many traces, in general, you want a match in the phx_app/lib/*
and I think it's more useful.
How about fetch by match /:otp_app/lib
path?
https://github.com/elixir-ecto/ecto_sql/pull/363/files#diff-9a458b905f34396e522038e878f83c957e4649c66a4a13f263bb8fcdcbbe744eR920
https://github.com/elixir-ecto/ecto_sql/pull/363/files#diff-9a458b905f34396e522038e878f83c957e4649c66a4a13f263bb8fcdcbbe744eR1042-R1070
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.
There's a trick here. I believe it works in 99% of the cases:
I changed the Process.info(self(), :current_stacktrace)
up in the pipeline:
https://github.com/elixir-ecto/ecto/blob/a04b0de384dbf21b4440162f3a0165c8d47e08bc/lib/ecto/repo.ex#L260
The usual path is something around:
Your code -> Your Repo -> Ecto.Repo -> Ecto internals -> Ecto adapter internals (+dbconnection, etc)
When getting the stacktrace at the ecto adapters, it would have a lot of random things.
But getting it in Ecto.Repo, what I see is usually:
{Process, :info, 2, .....}
{Ecto.Repo, :repo_function_called, ....}
{MyApp.Repo, :repo_function_called, ....}
{Calling code, .........}
As I strip the process.info from the stacktrace (not really useful :)), your code is usually at position 2.
The only situation I can see it not behaving this way is if you're using some library that increases indirection between Ecto and your code. None comes to mind. But maybe it is worth, yes, to go safer and do something like that.
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.
I'm thinking of maybe getting alwaays the one below {MyApp.Repo, ...}
instead of using numbers, which is kinda naive. But having some kind of configurability, as you did, may be the best... got to think about it
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.
We should do a Enum.drop instead and send the whole stacktrace. Let the entity who is logging figure out what to do with it.
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.
I'm not sure if I get you. I'm doing this here (ecto):
- https://github.com/elixir-ecto/ecto/blob/a04b0de384dbf21b4440162f3a0165c8d47e08bc/lib/ecto/repo.ex#L269
And then filtering for log in the function that we are commenting on. Do you think we should log the whole stacktrace instead of first non-ecto?
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.
Is this hint?ActiveSupport::BacktraceCleaner
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.
@v0idpwn
Hi!Happy new year!
I created stacktrace_cleaner.
Can you use it?
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.
Hey, @tashirosota, sorry for not answering earlier :), happy new year!!
I totally agree that Enum.at(stacktrace, 2)
is a problem, but I also don't want to tie it to path on Ecto itself. I've been thinking about it last few days, and probably the approach we will go with is:
- Find the last ecto module in stacktrace
- Return the next item
This is a bit naive, but should work for the general case. If this proves not to be enough, I'd be happy to add some interface where the user can plug their own stacktrace cleaner (it should be trivial to use your library to do it). But I think we probably shouldn't add more mandatory dependencies on Ecto.
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.
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.
I think yes, on favor of this one :). I will finish it this week and hopely we can merge it for next ecto release.
Thank you, you've been very helpful
Just pushed a commit that gets the first non-ecto entry. Is there anything else that should be done before merge? 🙂 |
lib/ecto/adapters/sql.ex
Outdated
reversed = Enum.reverse(stacktrace) | ||
|
||
reversed | ||
|> Enum.find_index(fn {module, _function, _arity, _metadata} -> |
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.
Do Enum.drop_while
it doesn't start with "Elixir.Ecto". Then check if it is an empty list, if not, it is the first element.
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.
Can't do it this way because we may have something like Enum
in the middle (its the case for Ecto.Multi
)
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.
I can be any operation from Enum. The point is that we should be able to traverse once instead of doing it twice. :)
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.
Just this comment and we are good to go. Ping me if you are not sure how to go ahead!
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.
I got a very simple solution with recursion. But I want to experiment a last bit more today :)
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.
Instead of find_index maybe find_value? Drop_while would also work :)
lib/ecto/adapters/sql.ex
Outdated
?., | ||
Atom.to_string(function), | ||
?/, | ||
inspect(arity), |
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.
There is a function called Exception.format_mfa
or similar. :)
d7f1c27
to
4e2da36
Compare
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.
Sorry I'm late.
LGTM!!
💚 💙 💜 💛 ❤️ |
Companion pr to elixir-ecto/ecto#3798