Skip to content
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

API client Series() call can't handle minTime/maxTime set by prometheus #614

Closed
jacksontj opened this issue Jul 2, 2019 · 17 comments · Fixed by #619
Closed

API client Series() call can't handle minTime/maxTime set by prometheus #614

jacksontj opened this issue Jul 2, 2019 · 17 comments · Fixed by #619
Assignees

Comments

@jacksontj
Copy link
Contributor

This is a bit of a convoluted error so I'll do my best to explain.

If an API call to /series is made without a start/end time prometheus sets minTime/maxTime as the value (https://github.com/prometheus/prometheus/blob/master/web/api/v1/api.go#L462). If I then turn around and use this time with the API client (to presumably send the same request) I get an error:

{
"status": "error",
"errorType": "execution",
"error": "bad_data: cannot parse \"292277025-08-17T23:12:54.999-08:00\" to a valid timestamp"
}

This is because the times used for minTime/maxTime can't be formatted to an RFC3339Nano timestamp. So for my use case in promxy I get a call from grafana (in this example) with no start/end time -- so prometheus sets the time to these min/max times but then I cannot pass that time down to another prometheus to fetch the data, as its not a valid timestamp.

Go playground showing the behavior: https://play.golang.org/p/hM_DWyv0JMK

So I'm not sure what we want to do exactly to handle this. Locally I have copied the min/max times into the client package and are optionally not setting the start/end times if they match. I'm not a major fan of the copy/paste of vars, but unfortunately those times are also private in the prometheus api/v1 package (https://github.com/prometheus/prometheus/blob/master/web/api/v1/api.go#L441). Alternatively we could make it so the client doesn't set the start/end if start/end are time.IsZero() which would allow the client/caller to pick when they don't send the timestamp (instead of us transparently doing it in the client).

jacksontj added a commit to jacksontj/client_golang that referenced this issue Jul 2, 2019
Fixes prometheus#614

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
@brian-brazil
Copy link
Contributor

That sounds like a bug on the Prometheus end, however I also recall that Go has some limits in terms of what it can handle time wise.

@jacksontj
Copy link
Contributor Author

@brian-brazil Yea, I could go either way on this TBH (client or server issue). If we were to tackle this server-side then IMO we'd want to pass some other time down the stack (presumably min/max that can be represented in what the API requires) -- right now the time we set is not expressible in the format the API requires.

@beorn7
Copy link
Member

beorn7 commented Jul 3, 2019

@krasi-georgiev assigning to you as the API expert. Perhaps you have an opinion/idea?

@brian-brazil
Copy link
Contributor

Something else that occurs to me is that if this is something that could also affect other languages, then we should probably fix it on the server.

@krasi-georgiev
Copy link
Contributor

+1 on fixing server side

@jacksontj
Copy link
Contributor Author

jacksontj commented Jul 3, 2019 via email

@brian-brazil
Copy link
Contributor

Hmm, looking a bit more this looks like a Go bug. The parser can only handle 4 digit years. golang/go#20555 is related, but different.

@jacksontj
Copy link
Contributor Author

jacksontj commented Jul 3, 2019

Well, as a workaround until it supports more than 4 digit year dates, we could change the min/max to:

minTime: "1970-01-01T00:00:00.0Z"
maxTime: "9999-12-31T23:59:59.999999999Z"

Which buys us 7980 years to sort that out :)

Alternatively we could implement parsing for the current min/max times

@jacksontj
Copy link
Contributor Author

@brian-brazil friendly bump on #614 (comment) :)

@brian-brazil
Copy link
Contributor

I'm not sure what the best way to deal with this is to be honest, as I don't think a Go fix is coming soon.

@jacksontj
Copy link
Contributor Author

Our options for a server-side fix are (1) set min/max time to something the time package can parse or (2) implement the time parsing ourselves (there's already a parseTime method, so it wouldn't be too bad).

Either approach is fine IMO we just have to pick one :)

@brian-brazil
Copy link
Contributor

The latter is probably better, I can imagine changing the guard value in future could cause issues. But I don't feel strongly on this.

@jacksontj
Copy link
Contributor Author

I had another idea, instead of implementing all the parsing I just added special-case checks for min/max time (prometheus/prometheus@32c3b7c -- part of prometheus/prometheus#5734) This way we can delay implementing the actual time parsing (hopefully upstream sorts that out?) but still be able to unmarshal our own time range :)

@brian-brazil
Copy link
Contributor

That's a good idea.

jacksontj added a commit to jacksontj/prometheus that referenced this issue Jul 6, 2019
Related to prometheus/client_golang#614

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
jacksontj added a commit to jacksontj/prometheus that referenced this issue Jul 7, 2019
Related to prometheus/client_golang#614

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
jacksontj added a commit to jacksontj/client_golang that referenced this issue Jul 7, 2019
Prometheus has issues parsing RFC3339Nano timestamps if the year has more than 4 digits, in addition it is the second-pass parse attempt. Since this is a client library and the interface is a `time.Time` it makes sense that we pick the clearest simplest format-- so I propose we use the `model.Time` representation of time in our communications to prometheus. This (1) removes the issues with timezones in those queries going downstream and (2) completely works around this prometheus#614 issue as the parsing mechanism in prometheus can handle those times in this format.

Related to prometheus#614
@jacksontj
Copy link
Contributor Author

In addition to the server fix, IMO we should do #617 as a (1) simplification and (2) more complete workaround on the client side.

jacksontj added a commit to jacksontj/client_golang that referenced this issue Jul 7, 2019
Prometheus has issues parsing RFC3339Nano timestamps if the year has more than 4 digits, in addition it is the second-pass parse attempt. Since this is a client library and the interface is a `time.Time` it makes sense that we pick the clearest simplest format-- so I propose we use the `model.Time` representation of time in our communications to prometheus. This (1) removes the issues with timezones in those queries going downstream and (2) completely works around this prometheus#614 issue as the parsing mechanism in prometheus can handle those times in this format.

Related to prometheus#614

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
@krasi-georgiev
Copy link
Contributor

Hm, why not leave as is so that we will know when the server is not behaving as it should?

brian-brazil pushed a commit to prometheus/prometheus that referenced this issue Jul 8, 2019
…5734)

* Add tests to ensure we can marshal and unmarshal our min/max times

Related to prometheus/client_golang#614

Instead of implementing all the time parsing, we can special-case handle
these 2 times. This means if times in this format show up that
time.Parse can't handle they will still error, but we can marshal/parse
our own min/max time

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
@jacksontj
Copy link
Contributor Author

The fix we put in on the server side is a hack really because of the shortcomings of stdlib time parse. The prom API already supports 2 timestamp formats, so it makes sense to change this client to the one that "just works"

jacksontj added a commit to jacksontj/client_golang that referenced this issue Jul 9, 2019
Prometheus has issues parsing RFC3339Nano timestamps if the year has more than 4 digits, in addition it is the second-pass parse attempt. Since this is a client library and the interface is a `time.Time` it makes sense that we pick the clearest simplest format-- so I propose we use the `model.Time` representation of time in our communications to prometheus. This (1) removes the issues with timezones in those queries going downstream and (2) completely works around this prometheus#614 issue as the parsing mechanism in prometheus can handle those times in this format.

Related to prometheus#614

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
jacksontj added a commit to jacksontj/client_golang that referenced this issue Jul 9, 2019
Prometheus has issues parsing RFC3339Nano timestamps if the year has more than 4 digits, in addition it is the second-pass parse attempt. Since this is a client library and the interface is a `time.Time` it makes sense that we pick the clearest simplest format-- so I propose we use the `model.Time` representation of time in our communications to prometheus. This (1) removes the issues with timezones in those queries going downstream and (2) completely works around this prometheus#614 issue as the parsing mechanism in prometheus can handle those times in this format.

Related to prometheus#614

Signed-off-by: Thomas Jackson <jacksontj.89@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants