@@ -4,62 +4,12 @@ import (
44 "context"
55 "errors"
66 "fmt"
7- "math"
87 "net/http"
9- "strconv"
10- "time"
118
12- "github.com/prometheus/common/model"
139 "github.com/prometheus/prometheus/promql"
1410 "github.com/prometheus/prometheus/util/annotations"
15- "github.com/weaveworks/common/httpgrpc"
16- )
17-
18- var (
19- // MinTime is the default timestamp used for the start of optional time ranges.
20- // Exposed to let downstream projects reference it.
21- //
22- // Historical note: This should just be time.Unix(math.MinInt64/1000, 0).UTC(),
23- // but it was set to a higher value in the past due to a misunderstanding.
24- // The value is still low enough for practical purposes, so we don't want
25- // to change it now, avoiding confusion for importers of this variable.
26- MinTime = time .Unix (math .MinInt64 / 1000 + 62135596801 , 0 ).UTC ()
27-
28- // MaxTime is the default timestamp used for the end of optional time ranges.
29- // Exposed to let downstream projects to reference it.
30- //
31- // Historical note: This should just be time.Unix(math.MaxInt64/1000, 0).UTC(),
32- // but it was set to a lower value in the past due to a misunderstanding.
33- // The value is still high enough for practical purposes, so we don't want
34- // to change it now, avoiding confusion for importers of this variable.
35- MaxTime = time .Unix (math .MaxInt64 / 1000 - 62135596801 , 999999999 ).UTC ()
36-
37- minTimeFormatted = MinTime .Format (time .RFC3339Nano )
38- maxTimeFormatted = MaxTime .Format (time .RFC3339Nano )
3911)
4012
41- const (
42- nanosecondsInMillisecond = int64 (time .Millisecond / time .Nanosecond )
43- )
44-
45- func timeToMillis (t time.Time ) int64 {
46- return t .UnixNano () / nanosecondsInMillisecond
47- }
48-
49- func extractQueryOpts (r * http.Request ) (promql.QueryOpts , error ) {
50- var duration time.Duration
51-
52- if strDuration := r .FormValue ("lookback_delta" ); strDuration != "" {
53- parsedDuration , err := ParseDuration (strDuration )
54- if err != nil {
55- return nil , fmt .Errorf ("error parsing lookback delta duration: %w" , err )
56- }
57- duration = parsedDuration
58- }
59-
60- return promql .NewPrometheusQueryOpts (r .FormValue ("stats" ) == "all" , duration ), nil
61- }
62-
6313const (
6414 statusSuccess = "success"
6515 statusError = "error"
@@ -129,79 +79,3 @@ func invalidParamError(err error, parameter string) apiFuncResult {
12979 errorBadData , fmt .Errorf ("invalid parameter %q: %w" , parameter , err ),
13080 }, nil , nil }
13181}
132-
133- func ParseTime (s string ) (time.Time , error ) {
134- if t , err := strconv .ParseFloat (s , 64 ); err == nil {
135- s , ns := math .Modf (t )
136- ns = math .Round (ns * 1000 ) / 1000
137- return time .Unix (int64 (s ), int64 (ns * float64 (time .Second ))).UTC (), nil
138- }
139- if t , err := time .Parse (time .RFC3339Nano , s ); err == nil {
140- return t , nil
141- }
142-
143- // Stdlib's time parser can only handle 4 digit years. As a workaround until
144- // that is fixed we want to at least support our own boundary times.
145- // Context: https://github.com/prometheus/client_golang/issues/614
146- // Upstream issue: https://github.com/golang/go/issues/20555
147- switch s {
148- case minTimeFormatted :
149- return MinTime , nil
150- case maxTimeFormatted :
151- return MaxTime , nil
152- }
153- return time.Time {}, fmt .Errorf ("cannot parse %q to a valid timestamp" , s )
154- }
155-
156- func ParseTimeMillis (s string ) (int64 , error ) {
157- t , err := ParseTime (s )
158- if err != nil {
159- return 0 , httpgrpc .Errorf (http .StatusBadRequest , err .Error ())
160- }
161-
162- return timeToMillis (t ), nil
163- }
164-
165- func ParseDuration (s string ) (time.Duration , error ) {
166- if d , err := strconv .ParseFloat (s , 64 ); err == nil {
167- ts := d * float64 (time .Second )
168- if ts > float64 (math .MaxInt64 ) || ts < float64 (math .MinInt64 ) {
169- return 0 , fmt .Errorf ("cannot parse %q to a valid duration. It overflows int64" , s )
170- }
171- return time .Duration (ts ), nil
172- }
173- if d , err := model .ParseDuration (s ); err == nil {
174- return time .Duration (d ), nil
175- }
176- return 0 , fmt .Errorf ("cannot parse %q to a valid duration" , s )
177- }
178-
179- func ParseDurationMillis (s string ) (int64 , error ) {
180- d , err := ParseDuration (s )
181- if err != nil {
182- return 0 , httpgrpc .Errorf (http .StatusBadRequest , err .Error ())
183- }
184-
185- return int64 (d / (time .Millisecond / time .Nanosecond )), nil
186- }
187-
188- func ParseTimeParam (r * http.Request , paramName string , defaultValue time.Time ) (time.Time , error ) {
189- val := r .FormValue (paramName )
190- if val == "" {
191- val = strconv .FormatInt (defaultValue .Unix (), 10 )
192- }
193- result , err := ParseTime (val )
194- if err != nil {
195- return time.Time {}, fmt .Errorf ("invalid time value for '%s': %w" , paramName , err )
196- }
197- return result , nil
198- }
199-
200- func ParseTimeParamMillis (r * http.Request , paramName string , defaultValue time.Time ) (int64 , error ) {
201- t , err := ParseTimeParam (r , paramName , defaultValue )
202- if err != nil {
203- return 0 , httpgrpc .Errorf (http .StatusBadRequest , err .Error ())
204- }
205-
206- return timeToMillis (t ), nil
207- }
0 commit comments