proposal: change for Go beginners (stack trace)Β #140
Description
What I understand
WithMessage()
adds a messageWithStack()
adds the current stackWrap[f]()
adds a message + stackNew|Errorf()
creates an new error with message + stack
History
If I remember correctly:
Wrap[f]()
was added firstWithMessage()
+WithStack()
were added later, becauseWrap[f]()
was "too much" => we don't need a stack trace for all "wrapped error". It is only useful for the "deepest" error.
When should we use each function
- New root error =>
New|Errorf()
(it will contain a stack trace) - Error returned by the std lib or a 3rd party lib =>
Wrap[f]()
(we want to add a stack trace) - Error returned by our own code (in my app) =>
WithMessage()
(we don't want to add more stack trace) - Error returned by a different goroutine =>
WithStack()
(I don't use it very often)
Who am I working with
- ~10 Go developers
- All beginners in Go (they were working with other languages previously)
- Not always very strict/careful
The problem
- They don't/can't understand where to use
Wrap[f]()
vsWithMessage()
- We're losing a lot of time during code review
- Checking if
Wrap[f]()
orWithMessage()
should be called - Explaining in which case we must use which function
- Starting again for each newcomer
- Checking if
The risks
- If we call
WithMessage()
instead ofWrap[f]()
=> we're missing the stack trace - If we call
Wrap[f]()
instead ofWithMessage()
=> we "pollute" our error logs
What we need
A function that wraps an error with a message, and optionnaly with a stack trace if it doesn't have already one.
What I tried
My initial idea was to write a custom helper function that would do as described previously.
Sadly, this is not easily doable.
I can't call WithStack()
or Wrap[f]()
because it would include the helper function call in the stack.
The solutions
New function
Add a new function to github.com/pkg/errors
, that is exactly like Wrap[f]()
, but doesn't add a stack trace if there is already one.
I don't really like this one, because it makes the package's interface more complex
Change behavior
Change Wrap[f]()
, and don't add a stack trace if there is already one.
This is my favorite solution.
I agree, it will change the existing behavior.
However, I think this is worth it.
I can't think of any use case that requires to call Wrap[f]()
several times and have several redundant stack traces.
Just fork
I can perfectly understand if you disagree, and don't want to update the current code.
In this case, I will just copy the code to our internal repo, and adapt the code to match our needs.
I don't really like this, because I would stop using github.com/pkg/errors
.
We're currently using it everywhere in our code.
I've been able to "extend" the behavior properly since the beginning.
The implementation
I've seen #122 and I really dislike the implementation.
It means that only internal github.com/pkg/errors
types can be used.
We can't create our own types anymore.
What I would do instead:
- iterates over all causes
- check if at least 1 error implements
StackTrace()