-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add storage.Warnings to client #562
Conversation
e45a706
to
a412d02
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.
I quick note now, but will do a full review soon.
@krasi-georgiev the main question is what the interface should be. Right now I'm wrapping the |
@krasi-georgiev bump? |
will review in 1-2 days. |
I think it should be something like:
|
@krasi-georgiev to clarify, you want to replace the From the upstream behavior warnings != error, so it seems incorrect for the client to be merging them. And if we decided that we wanted to then we'd definitely need a mechanism for the caller to determine what is an error vs a warning. In this proposed error struct thats a bit unclear. I'm also unclear what
|
maybe you are right lets try to keep these separately to be similiar to upstream. in that case why not keep it seperately starting from the client?
|
@krasi-georgiev It isn't split right now because I hadn't heard back on the plan -- #562 (comment) So it sounds like we want to keep warning/error separate all the way down? If so I can definitely do that. |
All the way down to the HTTP client doesn't quite work, at this client level all we do is return a resp, body, and error -- at this level we haven't unmarshaled the response enough to know if there are warnings. |
4175e10
to
13dc6f7
Compare
@krasi-georgiev here's it with warnings split all the way down |
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.
hm , now I see what you meant by typecasting the error type.
Now when it is completely separated it pollutes all other methods that don't really need it and end up with _, _, _, err = h.client.Do(ctx, req)
Do you think that maybe we can implement some custom API error interface like
something like
type ErrorAPI interface{
Error()
Warning()
}
For the error response, if we want to have a single return type, IMO we should go back to what I had before where we have a specific |
do you mean with typecasting? Do you think we can avoid typecasting by using an interface?
I don't think this is a problem. |
Yes I mean with typecasting. Otherwise if they want an error or warning
separately the client would have to convert out custom interface or stuck
over. So what I had before was a `Warnings` type that implemented the error
interface, so the caller could check if it's a warning
…On Fri, May 10, 2019, 12:57 AM Krasi Georgiev ***@***.***> wrote:
For the error response, if we want to have a single return type, IMO we
should go back to what I had before where we have a specific Warnings
struct that implements error.
do you mean with typecasting? Do you think we can avoid typecasting by
using an interface?
but do realize that will make the client interface different from the
internal interface.
I don't have a problem with that.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#562 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAMLPHLV4DWTCBIONZAO2NDPUUTHHANCNFSM4HJGU2TQ>
.
|
I was thinking something like this:
and than
so that the caller can use |
@krasi-georgiev Updated with a single interface for the error, some small cleanup required; but since we are going back and forth a bunch I figured I'll let you do an initial review before I spend the time cleaning it up all the way. |
yes, I think this is the best approach so far so go ahead with the cleanup and ping me when ready for a review. |
@krasi-georgiev Cleanup done, hopefully thats enough to get this in :) |
|
||
type Error interface { | ||
error | ||
Err() 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.
Why the need for Err() and 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.
Err()
returns the error itself. This is important if you want to check if the error is something in particular. This is especially important as we have been returning the err directly until now. So old code that did something like:
ret, err := client.DoSomething()
if err != nil {
return nil, err
}
would now be able to do something like
ret, err := client.DoSomething()
if err != nil && err.Err() != nil {
return nil, err.Err()
}
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.
hm I still don't see the need for this.
Can you give an example for how and where it is needed and why it can't be achieved by just using err.Error() ?
even without err.Err you can still have
if err != nil && err.Error() != "" {
return nil, err.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.
err.Error() returns a string, if you need to check that is a specific error type or something then it is not sufficient.
For example, when we do a client get we could get back an error from the HTTP library. In the client it looks like so:
_, body, apiErr := h.client.Do(ctx, req)
if apiErr != nil {
return AlertsResult{}, apiErr
}
So if I wanted to handle the specific error type of http.ProtocolError
I'd need to do something like:
if err != nil {
if typedErr, ok := err.Err().(*http.ProtocolError); ok {
// do something else
}
return nil, err
}
If we only have the string representation the people are forced to resort to string matching, which is a bad plan :)
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.
Yes I agree. Lets keep just
// Error .....
type Error interface {
// Error ......
Error() error
// Warnings returns a list of warnings
Warnings() []string
}
There are still few places without comments the go-lint complains 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.
As I'm thinking about this more, I think we want to stick with:
type Error interface{
error
Err() error
Warnings() []string
}
and change the implementations of Error()
(the string return) to check the warnings. This way its more-or-less backwards compatible -- although it would mean that warnings are errors (if you wanted to skip them you'd have to check the Err() method). This would make it more compatible, and a little less clunky.
If we want the default behavior to be that people have to check if it was an error or warning then I think going to some interface that doesn't adhere to the error
interface would be okay -- it will just be completely incompatible with all client usage.
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.
Yes you are right lets keep as is for now and will refactor if needed.
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.
@krasi-georgiev to clarify, do you want me to change the Error()
implementation to return something if there was a warning (e.g. if no error but warnings, return the warnings concated somehow)?
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.
@krasi-georgiev bump :)
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 am at kubecon so will be slow on replies.
I meant to keep it as
type Error interface{
error
Err() error
Warnings() []string
}
@krasi-georgiev PR updated to address 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.
I think these are the last nits I could find 😺
You are right about the interface lets keep as is for now and will refactor if needed.
|
||
type Error interface { | ||
error | ||
Err() 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.
Yes you are right lets keep as is for now and will refactor if needed.
LGTM |
Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com> Fixes prometheus#560
@krasi-georgiev squashed, should be ready for merge. |
Didn't check all the details, but no general remarks from my side. I trust you to do the right thing in detail. |
closes #560
This adds
storage.Warnings
to the error return of Query and QueryRange. Unfortunately the client.Do() method interface makes this a bit difficult to implement.So either we go down this path (where the specific error is a known type people should check for) or we need to change the Do() methods' interface to return a separate "warning" error.