mirror of
https://github.com/grafana/grafana.git
synced 2025-01-09 15:43:23 -06:00
azuremonitor: fix auto interval calculation on backend
Not needed for alerting (as the query intervalms will always be 0) but needed later when being called from the frontend)
This commit is contained in:
parent
a54484638d
commit
0b74860f55
@ -89,7 +89,7 @@ func (e *AzureMonitorDatasource) buildQueries(queries []*tsdb.Query, timeRange *
|
||||
urlComponents["metricDefinition"] = fmt.Sprintf("%v", azureMonitorTarget["metricDefinition"])
|
||||
urlComponents["resourceName"] = fmt.Sprintf("%v", azureMonitorTarget["resourceName"])
|
||||
|
||||
ub := URLBuilder{
|
||||
ub := urlBuilder{
|
||||
ResourceGroup: urlComponents["resourceGroup"],
|
||||
MetricDefinition: urlComponents["metricDefinition"],
|
||||
ResourceName: urlComponents["resourceName"],
|
||||
@ -100,9 +100,9 @@ func (e *AzureMonitorDatasource) buildQueries(queries []*tsdb.Query, timeRange *
|
||||
|
||||
timeGrain := fmt.Sprintf("%v", azureMonitorTarget["timeGrain"])
|
||||
if timeGrain == "auto" {
|
||||
autoInSeconds := e.findClosestAllowedIntervalMs(query.IntervalMs) / 1000
|
||||
autoInterval := e.findClosestAllowedIntervalMS(query.IntervalMs)
|
||||
tg := &TimeGrain{}
|
||||
timeGrain, err = tg.createISO8601DurationFromInterval(fmt.Sprintf("%vs", autoInSeconds))
|
||||
timeGrain, err = tg.createISO8601DurationFromIntervalMS(autoInterval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -288,7 +288,7 @@ func (e *AzureMonitorDatasource) parseResponse(queryRes *tsdb.QueryResult, data
|
||||
// findClosestAllowedIntervalMs is used for the auto time grain setting.
|
||||
// It finds the closest time grain from the list of allowed time grains for Azure Monitor
|
||||
// using the Grafana interval in milliseconds
|
||||
func (e *AzureMonitorDatasource) findClosestAllowedIntervalMs(intervalMs int64) int64 {
|
||||
func (e *AzureMonitorDatasource) findClosestAllowedIntervalMS(intervalMs int64) int64 {
|
||||
closest := allowedIntervalsMS[0]
|
||||
|
||||
for i, allowed := range allowedIntervalsMS {
|
||||
|
@ -240,13 +240,13 @@ func TestAzureMonitorDatasource(t *testing.T) {
|
||||
"2d": 172800000,
|
||||
}
|
||||
|
||||
closest := datasource.findClosestAllowedIntervalMs(intervals["3m"])
|
||||
closest := datasource.findClosestAllowedIntervalMS(intervals["3m"])
|
||||
So(closest, ShouldEqual, intervals["5m"])
|
||||
|
||||
closest = datasource.findClosestAllowedIntervalMs(intervals["10m"])
|
||||
closest = datasource.findClosestAllowedIntervalMS(intervals["10m"])
|
||||
So(closest, ShouldEqual, intervals["15m"])
|
||||
|
||||
closest = datasource.findClosestAllowedIntervalMs(intervals["2d"])
|
||||
closest = datasource.findClosestAllowedIntervalMS(intervals["2d"])
|
||||
So(closest, ShouldEqual, intervals["1d"])
|
||||
})
|
||||
})
|
||||
|
@ -4,6 +4,9 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
)
|
||||
|
||||
// TimeGrain handles convertions between
|
||||
@ -15,28 +18,24 @@ var (
|
||||
smallTimeUnits = []string{"hour", "minute", "h", "m"}
|
||||
)
|
||||
|
||||
func (tg *TimeGrain) createISO8601DurationFromInterval(interval string) (string, error) {
|
||||
if strings.Contains(interval, "ms") {
|
||||
func (tg *TimeGrain) createISO8601DurationFromIntervalMS(interval int64) (string, error) {
|
||||
formatted := tsdb.FormatDuration(time.Duration(interval) * time.Millisecond)
|
||||
|
||||
if strings.Contains(formatted, "ms") {
|
||||
return "PT1M", nil
|
||||
}
|
||||
|
||||
timeValueString := interval[0 : len(interval)-1]
|
||||
timeValueString := formatted[0 : len(formatted)-1]
|
||||
timeValue, err := strconv.Atoi(timeValueString)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Could not parse interval %v to an ISO 8061 duration", interval)
|
||||
}
|
||||
|
||||
unit := interval[len(interval)-1:]
|
||||
|
||||
if unit == "s" {
|
||||
toMinutes := (timeValue * 60) % 60
|
||||
unit := formatted[len(formatted)-1:]
|
||||
|
||||
if unit == "s" && timeValue < 60 {
|
||||
// mimumum interval is 1m for Azure Monitor
|
||||
if toMinutes < 1 {
|
||||
toMinutes = 1
|
||||
}
|
||||
|
||||
return tg.createISO8601Duration(toMinutes, "m"), nil
|
||||
return "PT1M", nil
|
||||
}
|
||||
|
||||
return tg.createISO8601Duration(timeValue, unit), nil
|
||||
|
@ -37,10 +37,14 @@ func TestTimeGrain(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
Convey("create ISO 8601 Duration from Grafana interval", func() {
|
||||
Convey("create ISO 8601 Duration from Grafana interval in milliseconds", func() {
|
||||
Convey("and interval is less than a minute", func() {
|
||||
durationMS, _ := tgc.createISO8601DurationFromInterval("100ms")
|
||||
durationS, _ := tgc.createISO8601DurationFromInterval("59s")
|
||||
durationMS, err := tgc.createISO8601DurationFromIntervalMS(100)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
durationS, err := tgc.createISO8601DurationFromIntervalMS(59999)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("should be rounded up to a minute as is the minimum interval for Azure Monitor", func() {
|
||||
So(durationMS, ShouldEqual, "PT1M")
|
||||
So(durationS, ShouldEqual, "PT1M")
|
||||
@ -48,8 +52,15 @@ func TestTimeGrain(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("and interval is more than a minute", func() {
|
||||
durationM, _ := tgc.createISO8601DurationFromInterval("10m")
|
||||
durationD, _ := tgc.createISO8601DurationFromInterval("2d")
|
||||
intervals := map[string]int64{
|
||||
"10m": 600000,
|
||||
"2d": 172800000,
|
||||
}
|
||||
durationM, err := tgc.createISO8601DurationFromIntervalMS(intervals["10m"])
|
||||
So(err, ShouldBeNil)
|
||||
durationD, err := tgc.createISO8601DurationFromIntervalMS(intervals["2d"])
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("should be rounded up to a minute as is the minimum interval for Azure Monitor", func() {
|
||||
So(durationM, ShouldEqual, "PT10M")
|
||||
So(durationD, ShouldEqual, "P2D")
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// URLBuilder builds the URL for calling the Azure Monitor API
|
||||
type URLBuilder struct {
|
||||
// urlBuilder builds the URL for calling the Azure Monitor API
|
||||
type urlBuilder struct {
|
||||
ResourceGroup string
|
||||
MetricDefinition string
|
||||
ResourceName string
|
||||
@ -14,7 +14,7 @@ type URLBuilder struct {
|
||||
|
||||
// Build checks the metric definition property to see which form of the url
|
||||
// should be returned
|
||||
func (ub *URLBuilder) Build() string {
|
||||
func (ub *urlBuilder) Build() string {
|
||||
|
||||
if strings.Count(ub.MetricDefinition, "/") > 1 {
|
||||
rn := strings.Split(ub.ResourceName, "/")
|
||||
|
@ -10,7 +10,7 @@ func TestURLBuilder(t *testing.T) {
|
||||
Convey("AzureMonitor URL Builder", t, func() {
|
||||
|
||||
Convey("when metric definition is in the short form", func() {
|
||||
ub := &URLBuilder{
|
||||
ub := &urlBuilder{
|
||||
ResourceGroup: "rg",
|
||||
MetricDefinition: "Microsoft.Compute/virtualMachines",
|
||||
ResourceName: "rn",
|
||||
@ -21,7 +21,7 @@ func TestURLBuilder(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("when metric definition is Microsoft.Storage/storageAccounts/blobServices", func() {
|
||||
ub := &URLBuilder{
|
||||
ub := &urlBuilder{
|
||||
ResourceGroup: "rg",
|
||||
MetricDefinition: "Microsoft.Storage/storageAccounts/blobServices",
|
||||
ResourceName: "rn1/default",
|
||||
@ -32,7 +32,7 @@ func TestURLBuilder(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("when metric definition is Microsoft.Storage/storageAccounts/fileServices", func() {
|
||||
ub := &URLBuilder{
|
||||
ub := &urlBuilder{
|
||||
ResourceGroup: "rg",
|
||||
MetricDefinition: "Microsoft.Storage/storageAccounts/fileServices",
|
||||
ResourceName: "rn1/default",
|
||||
|
@ -51,11 +51,11 @@ func TestInterval(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Format value", func() {
|
||||
So(formatDuration(time.Second*61), ShouldEqual, "1m")
|
||||
So(formatDuration(time.Millisecond*30), ShouldEqual, "30ms")
|
||||
So(formatDuration(time.Hour*23), ShouldEqual, "23h")
|
||||
So(formatDuration(time.Hour*24), ShouldEqual, "1d")
|
||||
So(formatDuration(time.Hour*24*367), ShouldEqual, "1y")
|
||||
So(FormatDuration(time.Second*61), ShouldEqual, "1m")
|
||||
So(FormatDuration(time.Millisecond*30), ShouldEqual, "30ms")
|
||||
So(FormatDuration(time.Hour*23), ShouldEqual, "23h")
|
||||
So(FormatDuration(time.Hour*24), ShouldEqual, "1d")
|
||||
So(FormatDuration(time.Hour*24*367), ShouldEqual, "1y")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user