Skip to content

Commit 5577d46

Browse files
authored
gtime: Move grafana/grafana intervalv2 functions in plugin-sdk-go (#886)
* Move GetIntervalFrom, ParseIntervalStringToTimeDuration and roundInterval * Remove roundInterval * fix * fix 2 * fix 3
1 parent b3749a7 commit 5577d46

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

backend/gtime/gtime.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"regexp"
66
"strconv"
7+
"strings"
78
"time"
89
)
910

@@ -117,3 +118,51 @@ func FormatInterval(inter time.Duration) string {
117118

118119
return "1ms"
119120
}
121+
122+
// GetIntervalFrom returns the minimum interval.
123+
// dsInterval is the string representation of data source min interval, if configured.
124+
// queryInterval is the string representation of query interval (min interval), e.g. "10ms" or "10s".
125+
// queryIntervalMS is a pre-calculated numeric representation of the query interval in milliseconds.
126+
func GetIntervalFrom(dsInterval, queryInterval string, queryIntervalMS int64, defaultInterval time.Duration) (time.Duration, error) {
127+
// Apparently we are setting default value of queryInterval to 0s now
128+
interval := queryInterval
129+
if interval == "0s" {
130+
interval = ""
131+
}
132+
if interval == "" {
133+
if queryIntervalMS != 0 {
134+
return time.Duration(queryIntervalMS) * time.Millisecond, nil
135+
}
136+
}
137+
if interval == "" && dsInterval != "" {
138+
interval = dsInterval
139+
}
140+
if interval == "" {
141+
return defaultInterval, nil
142+
}
143+
144+
parsedInterval, err := ParseIntervalStringToTimeDuration(interval)
145+
if err != nil {
146+
return time.Duration(0), err
147+
}
148+
149+
return parsedInterval, nil
150+
}
151+
152+
// ParseIntervalStringToTimeDuration converts a string representation of a expected (i.e. 1m30s) to time.Duration
153+
// this method copied from grafana/grafana/pkg/tsdb/intervalv2.go
154+
func ParseIntervalStringToTimeDuration(interval string) (time.Duration, error) {
155+
formattedInterval := strings.Replace(strings.Replace(interval, "<", "", 1), ">", "", 1)
156+
isPureNum, err := regexp.MatchString(`^\d+$`, formattedInterval)
157+
if err != nil {
158+
return time.Duration(0), err
159+
}
160+
if isPureNum {
161+
formattedInterval += "s"
162+
}
163+
parsedInterval, err := ParseDuration(formattedInterval)
164+
if err != nil {
165+
return time.Duration(0), err
166+
}
167+
return parsedInterval, nil
168+
}

backend/gtime/gtime_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,66 @@ func TestFormatInterval(t *testing.T) {
120120
})
121121
}
122122
}
123+
124+
func TestGetIntervalFrom(t *testing.T) {
125+
testCases := []struct {
126+
name string
127+
queryInterval string
128+
queryIntervalMs int64
129+
defaultInterval time.Duration
130+
expected time.Duration
131+
}{
132+
{"45s", "45s", 0, time.Second * 15, time.Second * 45},
133+
{"45", "45", 0, time.Second * 15, time.Second * 45},
134+
{"2m", "2m", 0, time.Second * 15, time.Minute * 2},
135+
{"1d", "1d", 0, time.Second * 15, time.Hour * 24},
136+
{"intervalMs", "", 45000, time.Second * 15, time.Second * 45},
137+
{"intervalMs sub-seconds", "", 45200, time.Second * 15, time.Millisecond * 45200},
138+
{"defaultInterval when interval empty", "", 0, time.Second * 15, time.Second * 15},
139+
{"defaultInterval when intervalMs 0", "", 0, time.Second * 15, time.Second * 15},
140+
}
141+
142+
for _, tc := range testCases {
143+
t.Run(tc.name, func(t *testing.T) {
144+
actual, err := GetIntervalFrom(tc.queryInterval, "", tc.queryIntervalMs, tc.defaultInterval)
145+
require.Nil(t, err)
146+
require.Equal(t, tc.expected, actual)
147+
})
148+
}
149+
}
150+
151+
func TestParseIntervalStringToTimeDuration(t *testing.T) {
152+
tcs := []struct {
153+
inp string
154+
duration time.Duration
155+
err *regexp.Regexp
156+
}{
157+
{inp: "1s", duration: time.Second},
158+
{inp: "1m", duration: time.Minute},
159+
{inp: "1h", duration: time.Hour},
160+
{inp: "1d", duration: 24 * time.Hour},
161+
{inp: "1w", duration: 7 * 24 * time.Hour},
162+
{inp: "2w", duration: 2 * 7 * 24 * time.Hour},
163+
{inp: "1M", duration: time.Duration(730.5 * float64(time.Hour))},
164+
{inp: "1y", duration: 365.25 * 24 * time.Hour},
165+
{inp: "5y", duration: 5 * 365.25 * 24 * time.Hour},
166+
{inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)},
167+
// ParseIntervalStringToTimeDuration specific conditions
168+
{inp: "10", duration: 10 * time.Second},
169+
{inp: "<10s>", duration: 10 * time.Second},
170+
{inp: "10s>", duration: 10 * time.Second},
171+
{inp: "<10s", duration: 10 * time.Second},
172+
}
173+
for i, tc := range tcs {
174+
t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) {
175+
res, err := ParseIntervalStringToTimeDuration(tc.inp)
176+
if tc.err == nil {
177+
require.NoError(t, err, "input %q", tc.inp)
178+
require.Equal(t, tc.duration, res, "input %q", tc.inp)
179+
} else {
180+
require.Error(t, err, "input %q", tc.inp)
181+
require.Regexp(t, tc.err, err.Error())
182+
}
183+
})
184+
}
185+
}

0 commit comments

Comments
 (0)