mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-20 07:19:17 +01:00
vmalert: add support for datasource.lookback
flag (#779)
New datasource flag `datasource.lookback` defines how far to look into past when evaluating queries. Address https://github.com/VictoriaMetrics/VictoriaMetrics/issues/668
This commit is contained in:
parent
82c3bbce34
commit
5dffc7a553
@ -166,6 +166,8 @@ The shortlist of configuration flags is the following:
|
|||||||
Optional basic auth password for -datasource.url
|
Optional basic auth password for -datasource.url
|
||||||
-datasource.basicAuth.username string
|
-datasource.basicAuth.username string
|
||||||
Optional basic auth username for -datasource.url
|
Optional basic auth username for -datasource.url
|
||||||
|
-datasource.lookback duration
|
||||||
|
Lookback defines how far to look into past when evaluating queries. For example, if datasource.lookback=5m then param "time" with value now()-5m will be added to every query.
|
||||||
-datasource.tlsCAFile string
|
-datasource.tlsCAFile string
|
||||||
Optional path to TLS CA file to use for verifying connections to -datasource.url. By default system CA is used
|
Optional path to TLS CA file to use for verifying connections to -datasource.url. By default system CA is used
|
||||||
-datasource.tlsCertFile string
|
-datasource.tlsCertFile string
|
||||||
|
@ -21,6 +21,9 @@ var (
|
|||||||
"By default system CA is used")
|
"By default system CA is used")
|
||||||
tlsServerName = flag.String("datasource.tlsServerName", "", "Optional TLS server name to use for connections to -datasource.url. "+
|
tlsServerName = flag.String("datasource.tlsServerName", "", "Optional TLS server name to use for connections to -datasource.url. "+
|
||||||
"By default the server name from -datasource.url is used")
|
"By default the server name from -datasource.url is used")
|
||||||
|
|
||||||
|
lookBack = flag.Duration("datasource.lookback", 0, "Lookback defines how far to look into past when evaluating queries. "+
|
||||||
|
"For example, if datasource.lookback=5m then param \"time\" with value now()-5m will be added to every query.")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init creates a Querier from provided flag values.
|
// Init creates a Querier from provided flag values.
|
||||||
@ -34,5 +37,5 @@ func Init() (Querier, error) {
|
|||||||
return nil, fmt.Errorf("failed to create transport: %w", err)
|
return nil, fmt.Errorf("failed to create transport: %w", err)
|
||||||
}
|
}
|
||||||
c := &http.Client{Transport: tr}
|
c := &http.Client{Transport: tr}
|
||||||
return NewVMStorage(*addr, *basicAuthUsername, *basicAuthPassword, c), nil
|
return NewVMStorage(*addr, *basicAuthUsername, *basicAuthPassword, *lookBack, c), nil
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type response struct {
|
type response struct {
|
||||||
@ -45,23 +46,25 @@ func (r response) metrics() ([]Metric, error) {
|
|||||||
return ms, nil
|
return ms, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryPath = "/api/v1/query?query="
|
|
||||||
|
|
||||||
// VMStorage represents vmstorage entity with ability to read and write metrics
|
// VMStorage represents vmstorage entity with ability to read and write metrics
|
||||||
type VMStorage struct {
|
type VMStorage struct {
|
||||||
c *http.Client
|
c *http.Client
|
||||||
queryURL string
|
queryURL string
|
||||||
basicAuthUser string
|
basicAuthUser string
|
||||||
basicAuthPass string
|
basicAuthPass string
|
||||||
|
lookBack time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const queryPath = "/api/v1/query?query="
|
||||||
|
|
||||||
// NewVMStorage is a constructor for VMStorage
|
// NewVMStorage is a constructor for VMStorage
|
||||||
func NewVMStorage(baseURL, basicAuthUser, basicAuthPass string, c *http.Client) *VMStorage {
|
func NewVMStorage(baseURL, basicAuthUser, basicAuthPass string, lookBack time.Duration, c *http.Client) *VMStorage {
|
||||||
return &VMStorage{
|
return &VMStorage{
|
||||||
c: c,
|
c: c,
|
||||||
basicAuthUser: basicAuthUser,
|
basicAuthUser: basicAuthUser,
|
||||||
basicAuthPass: basicAuthPass,
|
basicAuthPass: basicAuthPass,
|
||||||
queryURL: strings.TrimSuffix(baseURL, "/") + queryPath,
|
queryURL: strings.TrimSuffix(baseURL, "/") + queryPath,
|
||||||
|
lookBack: lookBack,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +73,12 @@ func (s *VMStorage) Query(ctx context.Context, query string) ([]Metric, error) {
|
|||||||
const (
|
const (
|
||||||
statusSuccess, statusError, rtVector = "success", "error", "vector"
|
statusSuccess, statusError, rtVector = "success", "error", "vector"
|
||||||
)
|
)
|
||||||
req, err := http.NewRequest("POST", s.queryURL+url.QueryEscape(query), nil)
|
q := s.queryURL + url.QueryEscape(query)
|
||||||
|
if s.lookBack > 0 {
|
||||||
|
lookBack := time.Now().UTC().Add(-s.lookBack)
|
||||||
|
q += fmt.Sprintf("&time=%d", lookBack.Unix())
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("POST", q, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -31,6 +33,13 @@ func TestVMSelectQuery(t *testing.T) {
|
|||||||
if r.URL.Query().Get("query") != query {
|
if r.URL.Query().Get("query") != query {
|
||||||
t.Errorf("expected %s in query param, got %s", query, r.URL.Query().Get("query"))
|
t.Errorf("expected %s in query param, got %s", query, r.URL.Query().Get("query"))
|
||||||
}
|
}
|
||||||
|
timeParam := r.URL.Query().Get("time")
|
||||||
|
if timeParam == "" {
|
||||||
|
t.Errorf("expected 'time' in query param, got nil instead")
|
||||||
|
}
|
||||||
|
if _, err := strconv.ParseInt(timeParam, 10, 64); err != nil {
|
||||||
|
t.Errorf("failed to parse 'time' query param: %s", err)
|
||||||
|
}
|
||||||
switch c {
|
switch c {
|
||||||
case 0:
|
case 0:
|
||||||
conn, _, _ := w.(http.Hijacker).Hijack()
|
conn, _, _ := w.(http.Hijacker).Hijack()
|
||||||
@ -52,7 +61,7 @@ func TestVMSelectQuery(t *testing.T) {
|
|||||||
|
|
||||||
srv := httptest.NewServer(mux)
|
srv := httptest.NewServer(mux)
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
am := NewVMStorage(srv.URL, basicAuthName, basicAuthPass, srv.Client())
|
am := NewVMStorage(srv.URL, basicAuthName, basicAuthPass, time.Minute, srv.Client())
|
||||||
if _, err := am.Query(ctx, query); err == nil {
|
if _, err := am.Query(ctx, query); err == nil {
|
||||||
t.Fatalf("expected connection error got nil")
|
t.Fatalf("expected connection error got nil")
|
||||||
}
|
}
|
||||||
@ -89,5 +98,4 @@ func TestVMSelectQuery(t *testing.T) {
|
|||||||
m[0].Labels[0].Name != expected.Labels[0].Name {
|
m[0].Labels[0].Name != expected.Labels[0].Name {
|
||||||
t.Fatalf("unexpected metric %+v want %+v", m[0], expected)
|
t.Fatalf("unexpected metric %+v want %+v", m[0], expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,5 +35,5 @@ func Init() (datasource.Querier, error) {
|
|||||||
return nil, fmt.Errorf("failed to create transport: %w", err)
|
return nil, fmt.Errorf("failed to create transport: %w", err)
|
||||||
}
|
}
|
||||||
c := &http.Client{Transport: tr}
|
c := &http.Client{Transport: tr}
|
||||||
return datasource.NewVMStorage(*addr, *basicAuthUsername, *basicAuthPassword, c), nil
|
return datasource.NewVMStorage(*addr, *basicAuthUsername, *basicAuthPassword, 0, c), nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user