Handle Interval Date Format similar to the JS variant

7e14e272fa
This commit is contained in:
wph95 2018-03-26 16:13:14 +08:00
parent 1e275d0cd1
commit d6cdc2497c
No known key found for this signature in database
GPG Key ID: C8B3F2A207A6AFDC
9 changed files with 1559 additions and 8 deletions

8
Gopkg.lock generated
View File

@ -295,6 +295,12 @@
packages = ["."]
revision = "7cafcd837844e784b526369c9bce262804aebc60"
[[projects]]
branch = "master"
name = "github.com/leibowitz/moment"
packages = ["."]
revision = "8548108dcca204a1110b99e5fec966817499fe84"
[[projects]]
branch = "master"
name = "github.com/lib/pq"
@ -642,6 +648,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "5e65aeace832f1b4be17e7ff5d5714513c40f31b94b885f64f98f2332968d7c6"
inputs-digest = "9895ff7b1516b9639d0fc280ca155c8958486656a2086fc45e91f727fccea0d2"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -201,3 +201,7 @@ ignored = [
[[constraint]]
name = "github.com/denisenkom/go-mssqldb"
revision = "270bc3860bb94dd3a3ffd047377d746c5e276726"
[[constraint]]
branch = "master"
name = "github.com/leibowitz/moment"

View File

@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/tsdb"
"github.com/leibowitz/moment"
"src/github.com/davecgh/go-spew/spew"
"strconv"
"strings"
@ -63,7 +64,7 @@ func (qp *ElasticSearchQueryParser) getQueryHeader() *QueryHeader {
}
header.SearchType = searchType
header.IgnoreUnavailable = true
header.Index = qp.getIndexList()
header.Index = getIndexList(qp.DsInfo.Database, qp.DsInfo.JsonData.Get("interval").MustString(""), qp.TimeRange)
if esVersion >= 56 {
header.MaxConcurrentShardRequests = qp.DsInfo.JsonData.Get("maxConcurrentShardRequests").MustInt()
@ -87,11 +88,42 @@ func (qp *ElasticSearchQueryParser) payloadReplace(payload string, model *simple
return payload, nil
}
func (qp *ElasticSearchQueryParser) getIndexList() string {
_, err := qp.DsInfo.JsonData.Get("interval").String()
if err != nil {
return qp.DsInfo.Database
func getIndexList(pattern string, interval string, timeRange *tsdb.TimeRange) string {
if interval == "" {
return pattern
}
// todo: support interval
return qp.DsInfo.Database
var indexes []string
indexParts := strings.Split(strings.TrimLeft(pattern, "["), "]")
indexBase := indexParts[0]
if len(indexParts) <= 1 {
return pattern
}
indexDateFormat := indexParts[1]
start := moment.NewMoment(timeRange.MustGetFrom())
end := moment.NewMoment(timeRange.MustGetTo())
indexes = append(indexes, fmt.Sprintf("%s%s", indexBase, start.Format(indexDateFormat)))
for start.IsBefore(*end) {
switch interval {
case "Hourly":
start = start.AddHours(1)
case "Daily":
start = start.AddDay()
case "Weekly":
start = start.AddWeeks(1)
case "Monthly":
start = start.AddMonths(1)
case "Yearly":
start = start.AddYears(1)
}
indexes = append(indexes, fmt.Sprintf("%s%s", indexBase, start.Format(indexDateFormat)))
}
return strings.Join(indexes, ",")
}

View File

@ -0,0 +1,49 @@
package elasticsearch
import (
"github.com/grafana/grafana/pkg/tsdb"
. "github.com/smartystreets/goconvey/convey"
"strconv"
"strings"
"testing"
)
func makeTime(hour int) string {
//unixtime 1500000000 == 2017-07-14T02:40:00+00:00
return strconv.Itoa((1500000000 + hour*60*60) * 1000)
}
func getIndexListByTime(pattern string, interval string, hour int) string {
timeRange := &tsdb.TimeRange{
From: makeTime(0),
To: makeTime(hour),
}
return getIndexList(pattern, interval, timeRange)
}
func TestElasticsearchGetIndexList(t *testing.T) {
Convey("Test Elasticsearch getIndex ", t, func() {
Convey("Parse Interval Formats", func() {
So(getIndexListByTime("[logstash-]YYYY.MM.DD", "Daily", 48),
ShouldEqual, "logstash-2017.07.14,logstash-2017.07.15,logstash-2017.07.16")
So(len(strings.Split(getIndexListByTime("[logstash-]YYYY.MM.DD.HH", "Hourly", 3), ",")),
ShouldEqual, 4)
So(getIndexListByTime("[logstash-]YYYY.W", "Weekly", 100),
ShouldEqual, "logstash-2017.28,logstash-2017.29")
So(getIndexListByTime("[logstash-]YYYY.MM", "Monthly", 700),
ShouldEqual, "logstash-2017.07,logstash-2017.08")
So(getIndexListByTime("[logstash-]YYYY", "Yearly", 10000),
ShouldEqual, "logstash-2017,logstash-2018,logstash-2019")
})
Convey("No Interval", func() {
index := getIndexListByTime("logstash-test", "", 1)
So(index, ShouldEqual, "logstash-test")
})
})
}

75
vendor/github.com/leibowitz/moment/diff.go generated vendored Normal file
View File

@ -0,0 +1,75 @@
package moment
import (
"fmt"
"math"
"time"
)
// @todo In months/years requires the old and new to calculate correctly, right?
// @todo decide how to handle rounding (i.e. always floor?)
type Diff struct {
duration time.Duration
}
func (d *Diff) InSeconds() int {
return int(d.duration.Seconds())
}
func (d *Diff) InMinutes() int {
return int(d.duration.Minutes())
}
func (d *Diff) InHours() int {
return int(d.duration.Hours())
}
func (d *Diff) InDays() int {
return int(math.Floor(float64(d.InSeconds()) / 86400))
}
// This depends on where the weeks fall?
func (d *Diff) InWeeks() int {
return int(math.Floor(float64(d.InDays() / 7)))
}
func (d *Diff) InMonths() int {
return 0
}
func (d *Diff) InYears() int {
return 0
}
// http://momentjs.com/docs/#/durations/humanize/
func (d *Diff) Humanize() string {
diffInSeconds := d.InSeconds()
if diffInSeconds <= 45 {
return fmt.Sprintf("%d seconds ago", diffInSeconds)
} else if diffInSeconds <= 90 {
return "a minute ago"
}
diffInMinutes := d.InMinutes()
if diffInMinutes <= 45 {
return fmt.Sprintf("%d minutes ago", diffInMinutes)
} else if diffInMinutes <= 90 {
return "an hour ago"
}
diffInHours := d.InHours()
if diffInHours <= 22 {
return fmt.Sprintf("%d hours ago", diffInHours)
} else if diffInHours <= 36 {
return "a day ago"
}
return "diff is in days"
}
// In Months
// In years

1185
vendor/github.com/leibowitz/moment/moment.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

100
vendor/github.com/leibowitz/moment/moment_parser.go generated vendored Normal file
View File

@ -0,0 +1,100 @@
package moment
import (
"regexp"
"strings"
)
type MomentParser struct{}
var (
date_pattern = regexp.MustCompile("(LT|LL?L?L?|l{1,4}|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|Q)")
)
/*
+ <stdOrdinal> S (makes any number before it ordinal)
+ stdDayOfYear 1,2,365
+ stdDayOfYearZero 001, 002, 365
+ stdDayOfWeek w 0, 1, 2 numeric day of the week (0 = sunday)
+ stdDayOfWeekISO N 1 = Monday
+ stdWeekOfYear W Iso week number of year
+ stdUnix U
+ stdQuarter
*/
// Thanks to https://github.com/fightbulc/moment.php for replacement keys and regex
var moment_replacements = map[string]string{
"M": "1", // stdNumMonth 1 2 ... 11 12
"Mo": "1<stdOrdinal>", // stdNumMonth 1st 2nd ... 11th 12th
"MM": "01", // stdZeroMonth 01 02 ... 11 12
"MMM": "Jan", // stdMonth Jan Feb ... Nov Dec
"MMMM": "January", // stdLongMonth January February ... November December
"D": "2", // stdDay 1 2 ... 30 30
"Do": "2<stdOrdinal>", // stdDay 1st 2nd ... 30th 31st @todo support st nd th etch
"DD": "02", // stdZeroDay 01 02 ... 30 31
"DDD": "<stdDayOfYear>", // Day of the year 1 2 ... 364 365
"DDDo": "<stdDayOfYear><stdOrdinal>", // Day of the year 1st 2nd ... 364th 365th
"DDDD": "<stdDayOfYearZero>", // Day of the year 001 002 ... 364 365 @todo****
"d": "<stdDayOfWeek>", // Numeric representation of day of the week 0 1 ... 5 6
"do": "<stdDayOfWeek><stdOrdinal>", // 0th 1st ... 5th 6th
"dd": "Mon", // ***Su Mo ... Fr Sa @todo
"ddd": "Mon", // Sun Mon ... Fri Sat
"dddd": "Monday", // stdLongWeekDay Sunday Monday ... Friday Saturday
"e": "<stdDayOfWeek>", // Numeric representation of day of the week 0 1 ... 5 6 @todo
"E": "<stdDayOfWeekISO>", // ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) 1 2 ... 6 7 @todo
"w": "<stdWeekOfYear>", // 1 2 ... 52 53
"wo": "<stdWeekOfYear><stdOrdinal>", // 1st 2nd ... 52nd 53rd
"ww": "<stdWeekOfYear>", // ***01 02 ... 52 53 @todo
"W": "<stdWeekOfYear>", // 1 2 ... 52 53
"Wo": "<stdWeekOfYear><stdOrdinal>", // 1st 2nd ... 52nd 53rd
"WW": "<stdWeekOfYear>", // ***01 02 ... 52 53 @todo
"YY": "06", // stdYear 70 71 ... 29 30
"YYYY": "2006", // stdLongYear 1970 1971 ... 2029 2030
// "gg" : "o", // ISO-8601 year number 70 71 ... 29 30 @todo
// "gggg" : "o", // ***1970 1971 ... 2029 2030 @todo
// "GG" : "o", //70 71 ... 29 30 @todo
// "GGGG" : "o", // ***1970 1971 ... 2029 2030 @todo
"Q": "<stdQuarter>",
"A": "PM", // stdPM AM PM
"a": "pm", // stdpm am pm
"H": "<stdHourNoZero>", // stdHour 0 1 ... 22 23
"HH": "15", // 00 01 ... 22 23
"h": "3", // stdHour12 1 2 ... 11 12
"hh": "03", // stdZeroHour12 01 02 ... 11 12
"m": "4", // stdZeroMinute 0 1 ... 58 59
"mm": "04", // stdZeroMinute 00 01 ... 58 59
"s": "5", // stdSecond 0 1 ... 58 59
"ss": "05", // stdZeroSecond ***00 01 ... 58 59
// "S" : "", //0 1 ... 8 9
// "SS" : "", //0 1 ... 98 99
// "SSS" : "", //0 1 ... 998 999
"z": "MST", //EST CST ... MST PST
"zz": "MST", //EST CST ... MST PST
"Z": "Z07:00", // stdNumColonTZ -07:00 -06:00 ... +06:00 +07:00
"ZZ": "-0700", // stdNumTZ -0700 -0600 ... +0600 +0700
"X": "<stdUnix>", // Seconds since unix epoch 1360013296
"LT": "3:04 PM", // 8:30 PM
"L": "01/02/2006", //09/04/1986
"l": "1/2/2006", //9/4/1986
"LL": "January 2<stdOrdinal> 2006", //September 4th 1986 the php s flag isn't supported
"ll": "Jan 2 2006", //Sep 4 1986
"LLL": "January 2<stdOrdinal> 2006 3:04 PM", //September 4th 1986 8:30 PM @todo the php s flag isn't supported
"lll": "Jan 2 2006 3:04 PM", //Sep 4 1986 8:30 PM
"LLLL": "Monday, January 2<stdOrdinal> 2006 3:04 PM", //Thursday, September 4th 1986 8:30 PM the php s flag isn't supported
"llll": "Mon, Jan 2 2006 3:04 PM", //Thu, Sep 4 1986 8:30 PM
}
func (p *MomentParser) Convert(layout string) string {
var match [][]string
if match = date_pattern.FindAllStringSubmatch(layout, -1); match == nil {
return layout
}
for i := range match {
if replace, ok := moment_replacements[match[i][0]]; ok {
layout = strings.Replace(layout, match[i][0], replace, 1)
}
}
return layout
}

32
vendor/github.com/leibowitz/moment/parse_day.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
package moment
import (
"fmt"
"strings"
"time"
)
var (
days = []time.Weekday{
time.Sunday,
time.Monday,
time.Tuesday,
time.Wednesday,
time.Thursday,
time.Friday,
time.Saturday,
}
)
func ParseWeekDay(day string) (time.Weekday, error) {
day = strings.ToLower(day)
for _, d := range days {
if day == strings.ToLower(d.String()) {
return d, nil
}
}
return -1, fmt.Errorf("Unable to parse %s as week day", day)
}

68
vendor/github.com/leibowitz/moment/strftime_parser.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
package moment
import (
"regexp"
"strings"
)
type StrftimeParser struct{}
var (
replacements_pattern = regexp.MustCompile("%[mbhBedjwuaAVgyGYpPkHlIMSZzsTrRTDFXx]")
)
// Not implemented
// U
// C
var strftime_replacements = map[string]string{
"%m": "01", // stdZeroMonth 01 02 ... 11 12
"%b": "Jan", // stdMonth Jan Feb ... Nov Dec
"%h": "Jan",
"%B": "January", // stdLongMonth January February ... November December
"%e": "2", // stdDay 1 2 ... 30 30
"%d": "02", // stdZeroDay 01 02 ... 30 31
"%j": "<stdDayOfYear>", // Day of the year ***001 002 ... 364 365 @todo****
"%w": "<stdDayOfWeek>", // Numeric representation of day of the week 0 1 ... 5 6
"%u": "<stdDayOfWeekISO>", // ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) 1 2 ... 6 7 @todo
"%a": "Mon", // Sun Mon ... Fri Sat
"%A": "Monday", // stdLongWeekDay Sunday Monday ... Friday Saturday
"%V": "<stdWeekOfYear>", // ***01 02 ... 52 53 @todo begin with zeros
"%g": "06", // stdYear 70 71 ... 29 30
"%y": "06",
"%G": "2006", // stdLongYear 1970 1971 ... 2029 2030
"%Y": "2006",
"%p": "PM", // stdPM AM PM
"%P": "pm", // stdpm am pm
"%k": "15", // stdHour 0 1 ... 22 23
"%H": "15", // 00 01 ... 22 23
"%l": "3", // stdHour12 1 2 ... 11 12
"%I": "03", // stdZeroHour12 01 02 ... 11 12
"%M": "04", // stdZeroMinute 00 01 ... 58 59
"%S": "05", // stdZeroSecond ***00 01 ... 58 59
"%Z": "MST", //EST CST ... MST PST
"%z": "-0700", // stdNumTZ -0700 -0600 ... +0600 +0700
"%s": "<stdUnix>", // Seconds since unix epoch 1360013296
"%r": "03:04:05 PM",
"%R": "15:04",
"%T": "15:04:05",
"%D": "01/02/06",
"%F": "2006-01-02",
"%X": "15:04:05",
"%x": "01/02/06",
}
func (p *StrftimeParser) Convert(layout string) string {
var match [][]string
if match = replacements_pattern.FindAllStringSubmatch(layout, -1); match == nil {
return layout
}
for i := range match {
if replace, ok := strftime_replacements[match[i][0]]; ok {
layout = strings.Replace(layout, match[i][0], replace, 1)
}
}
return layout
}