-
Notifications
You must be signed in to change notification settings - Fork 18k
context: Cannot tell which deadline or timeout cause expiration #35791
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
Comments
API backward compatibility-wise, I have a few ideas of ways to add support to this. I think the implementation of any solution is straightforward, backward compatibility is the hardest part. Solutions depend on what exactly should be considered part of the API of the context package. It's not stated in the docs, but it's suggested in https://github.com/golang/go/wiki/CodeReviewComments#contexts to not create custom Context types. That suggests that adding methods to the context.Context does not break backward compatibility. If so, we can add a Origin() method that returns some value that can be associated with the originating deadline or cancellation. It seems ambiguous to me whether Context.Err() is allowed to return values other than context.Canceled and context.DeadlineExceeded. If it can return other errors, we can add new error values that contain origination information. These errors can be errors.Is one of the two existing sentinal values. If none of those pass the backward compatibility check, then we can add a new method/interface for the Origin() method, which all contexts are guaranteed to implement, and/or provide an Origin(Context) function like errors.Unwrap(). For adding originating information, we can add new functions WithCancelOrigin or WithDeadlineOrigin that accept a new parameter which is some origination information that would be queryable via one of the previous APIs, if it caused the context cancellation. The existing With* functions would be equivalent to calling the With*Origin functions with some generic origination value. |
See also #26356 I am currently handling an outage that is made more difficult because I can't tell why a context was canceled. It's not fun. |
Unfortunately I think it will be difficult to support this in a backwards-compatible way, because existing client code assumes that ctx.Err() is either nil, context.Canceled, or context.DeadlineExceeded:
Switching such client code to use In hindsight, these error values should not have been exported, and we should have provided functions like If we want to change this, we will need to introduce these functions long with lint/vet checks to complain about directly using the original values, and a go fix command to update client code (tricky, since we'll need to fix code that does CC @rsc |
There's also this backwards-compatible proposal from @bcmills : |
Can we mark this as a duplicate and close it in favor of #26356 ? |
Yes, done. Thanks. |
It is not currently possible to tell which deadline or timeout caused a context to expire. This makes debugging timeouts impossible.
Here's an example of when this is a problem: we have some RPC that is constantly failing because of context.DeadlineExceeded. We want to figure out which deadline is being exceed so we can evaluate whether we should increase it. The code looks like the following (may not be correct or idiomatic, demonstrative only):
There is no convenient way to tell whether Foo or Bar's deadline caused the context to expire. It is possible, strictly speaking:
Note that the above code is non-trivial to get right (I'm still not sure it's completely correct/bulletproof).
The text was updated successfully, but these errors were encountered: