-
Notifications
You must be signed in to change notification settings - Fork 38.7k
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
[e2e] Dump the stacktrace while an error occurs #80979
[e2e] Dump the stacktrace while an error occurs #80979
Conversation
/assign @timothysc @alejandrox1 |
/area e2e-test-framework |
@@ -1327,6 +1328,8 @@ func ExpectNoError(err error, explain ...interface{}) { | |||
func ExpectNoErrorWithOffset(offset int, err error, explain ...interface{}) { | |||
if err != nil { | |||
e2elog.Logf("Unexpected error occurred: %v", err) | |||
// Dump the stacktrace while an error occurs | |||
debug.PrintStack() | |||
} |
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.
Although panic
could print the stacktrace but it will exit the program. So using debug.PrintStack()
instead.
/retest |
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 like it!
This will be helpful on errors.
/cc @johnSchnake
/lgtm
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jiatongw, timothysc The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@@ -1340,6 +1343,8 @@ func ExpectNoErrorWithRetries(fn func() error, maxRetries int, explain ...interf | |||
return | |||
} | |||
e2elog.Logf("(Attempt %d of %d) Unexpected error occurred: %v", i+1, maxRetries, err) | |||
// Dump the stacktrace while an error occurs | |||
debug.PrintStack() |
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.
If we're doing retries it seems like we expect errors and wouldn't want/need the stacktrace.
Can we move this down so that we only dump the trace here if we run out of retries and are actually bubbling up the error?
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.
My thought is that it may have different reasons to cause the retry fail each time. So for each retry I chose to print the stack.
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.
any comments?
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.
Although that can happen; it has never been the case in my experience. Usually the same error happens 5 times so only the last one matters. OR you get an "error" which was somewhat expected (like polling for a service to come up) so you see 4 errors (and now 4 entire stack traces) even though the test goes onto pass.
My preference would still be for just the trace at the end, but I don't feel that strongly if you prefer this.
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.
This make more sense. I will move the printstack() out of the loop
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.
Let me know when you've made the changes and I'll re-review and remove the hold
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.
Ready to re-review
test/e2e/framework/util.go
Outdated
@@ -1327,6 +1328,8 @@ func ExpectNoError(err error, explain ...interface{}) { | |||
func ExpectNoErrorWithOffset(offset int, err error, explain ...interface{}) { | |||
if err != nil { | |||
e2elog.Logf("Unexpected error occurred: %v", err) | |||
// Dump the stacktrace while an error occurs |
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.
nit: I don't think the comments add any helpful information in either place. I'd just remove them.
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.
Deleted the comment
/hold |
2c59b25
to
cd048e3
Compare
/retest |
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 that the PrintStack will be useful for all of our Expect wrappers - i.e. not only these two.
test/e2e/framework/util.go
Outdated
@@ -1342,6 +1344,7 @@ func ExpectNoErrorWithRetries(fn func() error, maxRetries int, explain ...interf | |||
} | |||
e2elog.Logf("(Attempt %d of %d) Unexpected error occurred: %v", i+1, maxRetries, err) | |||
} | |||
debug.PrintStack() |
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.
should this PrintStack call should only happen if err != nil ?
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.
@neolit123 For wrappers like ExpectEqual
and ExpectNotEqual
, we need to put the PrintStack
into a condition statement to avoid it dump the stacktrace every time the wrappers be called. But gomega.Expect()
has no return value. I don't have any better insights to do some change in the wrappers. But there is a potential way, similar like this: For those tests that call ExpectEqual/ExpectNotEqual
, have a try..catch
thing. If exception happens, then call PrintStack()
. But Go doesn't have this kind of mechanism so this may involve a lot of changes. Or do you have any insights ?
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.
Capture the stdout/stderr after ExpectEqual/ExpectNotEqual
is also a potential solution. Need to implement a wrappers for the capture behavior.
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 my comment here was about this.
should this PrintStack call should only happen if err != nil ?
if err != nil {
debug.PrintStack()
}
otherwise we are printing a stack trace even if there is no error in the retires.
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.
ready to re-review
that's what i meant. if we add similar checks it should work e.g.
these need reflection on the interfaces to see if they are of the same type and equal.
|
That's a better solution. Thanks |
cd048e3
to
b501b34
Compare
3ba9716
to
a9ce198
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.
thanks for the update @jiatongw
/lgtm
but i'd prefer if someone else has a look too.
/assign @johnSchnake
/hold
/retest |
test/e2e/framework/util.go
Outdated
if reflect.TypeOf(actual) != reflect.TypeOf(extra) { | ||
e2elog.Logf("Unexpected unequal occurred: %v and %v", actual, extra) | ||
debug.PrintStack() | ||
} else if reflect.ValueOf(actual) != reflect.ValueOf(extra) { |
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.
This is not the type of comparison you want. From the godocs:
To compare two Values, compare the results of the Interface method. Using == on two Values does not compare the underlying values they represent.
I wouldn't even use the Interface
since it gets confusing to anyone about when/how they can use certain reflect
methods.
It seems like in these two cases we should be using the actual match that ginkgo will do, just leverage those without the Expect
:
if isEqual, _ := gomega.Equal(extra).Match(actual); isEqual{
...
}
Double-check me on that syntax but I think thats the way it would be written.
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.
Hi @johnSchnake , based on the doc https://onsi.github.io/gomega/#provided-matchers, I can't find a use like gomega.Equal(extra).Match(actual)
but I think I can use reflect.DeepEqual
to compare ACTUAL with EXPECTED, which is the gomega.Equal
implementation.
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.
They are all exported types/interfaces so we should just leverage what they've already written. For instance, they dont just do reflect.DeepEqual
but have an optimization in place. I don't want to have to maintain a separate method which could drift and doesn't have any justification/benefit over using theirs.
//For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding-your-own-matchers
type GomegaMatcher interface {
Match(actual interface{}) (success bool, err error)
FailureMessage(actual interface{}) (message string)
...
Equal matcher implementation:
https://github.com/kubernetes/kubernetes/blob/master/vendor/github.com/onsi/gomega/matchers/equal_matcher.go#L15-L28
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.
@johnSchnake could you re-review? Thanks!
/cc @oomichi |
Signed-off-by: Jiatong Wang <wangjiatong@vmware.com>
a9ce198
to
9a2ccc2
Compare
/lgtm |
What type of PR is this?
/kind cleanup
What this PR does / why we need it:
It's difficult to navigate when the error is generic, so dumping the stacktrace is worthwhile.
Reference: #34059
Does this PR introduce a user-facing change?: