diff --git a/app/vmalert/datasource/init.go b/app/vmalert/datasource/init.go index 891e7f991e..d18dad2208 100644 --- a/app/vmalert/datasource/init.go +++ b/app/vmalert/datasource/init.go @@ -12,7 +12,7 @@ import ( var ( addr = flag.String("datasource.url", "", "VictoriaMetrics or vmselect url. Required parameter. "+ - "E.g. http://127.0.0.1:8428") + "E.g. http://127.0.0.1:8428 . See also -remoteRead.disablePathAppend") appendTypePrefix = flag.Bool("datasource.appendTypePrefix", false, "Whether to add type prefix to -datasource.url based on the query type. Set to true if sending different query types to the vmselect URL.") basicAuthUsername = flag.String("datasource.basicAuth.username", "", "Optional basic auth username for -datasource.url") diff --git a/app/vmalert/datasource/vm.go b/app/vmalert/datasource/vm.go index 73d16fd8ad..0b60bbcde9 100644 --- a/app/vmalert/datasource/vm.go +++ b/app/vmalert/datasource/vm.go @@ -24,20 +24,18 @@ type VMStorage struct { dataSourceType Type evaluationInterval time.Duration extraParams url.Values - disablePathAppend bool } // Clone makes clone of VMStorage, shares http client. func (s *VMStorage) Clone() *VMStorage { return &VMStorage{ - c: s.c, - authCfg: s.authCfg, - datasourceURL: s.datasourceURL, - lookBack: s.lookBack, - queryStep: s.queryStep, - appendTypePrefix: s.appendTypePrefix, - dataSourceType: s.dataSourceType, - disablePathAppend: s.disablePathAppend, + c: s.c, + authCfg: s.authCfg, + datasourceURL: s.datasourceURL, + lookBack: s.lookBack, + queryStep: s.queryStep, + appendTypePrefix: s.appendTypePrefix, + dataSourceType: s.dataSourceType, } } @@ -57,16 +55,15 @@ func (s *VMStorage) BuildWithParams(params QuerierParams) Querier { } // NewVMStorage is a constructor for VMStorage -func NewVMStorage(baseURL string, authCfg *promauth.Config, lookBack time.Duration, queryStep time.Duration, appendTypePrefix bool, c *http.Client, disablePathAppend bool) *VMStorage { +func NewVMStorage(baseURL string, authCfg *promauth.Config, lookBack time.Duration, queryStep time.Duration, appendTypePrefix bool, c *http.Client) *VMStorage { return &VMStorage{ - c: c, - authCfg: authCfg, - datasourceURL: strings.TrimSuffix(baseURL, "/"), - appendTypePrefix: appendTypePrefix, - lookBack: lookBack, - queryStep: queryStep, - dataSourceType: NewPrometheusType(), - disablePathAppend: disablePathAppend, + c: c, + authCfg: authCfg, + datasourceURL: strings.TrimSuffix(baseURL, "/"), + appendTypePrefix: appendTypePrefix, + lookBack: lookBack, + queryStep: queryStep, + dataSourceType: NewPrometheusType(), } } diff --git a/app/vmalert/datasource/vm_prom_api.go b/app/vmalert/datasource/vm_prom_api.go index 5411fa1813..6b72efca86 100644 --- a/app/vmalert/datasource/vm_prom_api.go +++ b/app/vmalert/datasource/vm_prom_api.go @@ -2,12 +2,18 @@ package datasource import ( "encoding/json" + "flag" "fmt" "net/http" "strconv" "time" ) +var ( + disablePathAppend = flag.Bool("remoteRead.disablePathAppend", false, "Whether to disable automatic appending of '/api/v1/query' path "+ + "to the configured -datasource.url and -remoteRead.url") +) + type promResponse struct { Status string `json:"status"` ErrorType string `json:"errorType"` @@ -108,18 +114,12 @@ func parsePrometheusResponse(req *http.Request, resp *http.Response) ([]Metric, } } -const ( - prometheusInstantPath = "/api/v1/query" - prometheusRangePath = "/api/v1/query_range" - prometheusPrefix = "/prometheus" -) - func (s *VMStorage) setPrometheusInstantReqParams(r *http.Request, query string, timestamp time.Time) { if s.appendTypePrefix { - r.URL.Path += prometheusPrefix + r.URL.Path += "/prometheus" } - if !s.disablePathAppend { - r.URL.Path += prometheusInstantPath + if !*disablePathAppend { + r.URL.Path += "/api/v1/query" } q := r.URL.Query() if s.lookBack > 0 { @@ -136,10 +136,10 @@ func (s *VMStorage) setPrometheusInstantReqParams(r *http.Request, query string, func (s *VMStorage) setPrometheusRangeReqParams(r *http.Request, query string, start, end time.Time) { if s.appendTypePrefix { - r.URL.Path += prometheusPrefix + r.URL.Path += "/prometheus" } - if !s.disablePathAppend { - r.URL.Path += prometheusRangePath + if !*disablePathAppend { + r.URL.Path += "/api/v1/query_range" } q := r.URL.Query() q.Add("start", fmt.Sprintf("%d", start.Unix())) diff --git a/app/vmalert/datasource/vm_test.go b/app/vmalert/datasource/vm_test.go index f15bf57403..09bf4fe044 100644 --- a/app/vmalert/datasource/vm_test.go +++ b/app/vmalert/datasource/vm_test.go @@ -85,7 +85,7 @@ func TestVMInstantQuery(t *testing.T) { if err != nil { t.Fatalf("unexpected: %s", err) } - s := NewVMStorage(srv.URL, authCfg, time.Minute, 0, false, srv.Client(), false) + s := NewVMStorage(srv.URL, authCfg, time.Minute, 0, false, srv.Client()) p := NewPrometheusType() pq := s.BuildWithParams(QuerierParams{DataSourceType: &p, EvaluationInterval: 15 * time.Second}) @@ -196,7 +196,7 @@ func TestVMRangeQuery(t *testing.T) { if err != nil { t.Fatalf("unexpected: %s", err) } - s := NewVMStorage(srv.URL, authCfg, time.Minute, 0, false, srv.Client(), false) + s := NewVMStorage(srv.URL, authCfg, time.Minute, 0, false, srv.Client()) p := NewPrometheusType() pq := s.BuildWithParams(QuerierParams{DataSourceType: &p, EvaluationInterval: 15 * time.Second}) @@ -252,18 +252,7 @@ func TestRequestParams(t *testing.T) { dataSourceType: NewPrometheusType(), }, func(t *testing.T, r *http.Request) { - checkEqualString(t, prometheusInstantPath, r.URL.Path) - }, - }, - { - "prometheus path with disablePathAppend", - false, - &VMStorage{ - dataSourceType: NewPrometheusType(), - disablePathAppend: true, - }, - func(t *testing.T, r *http.Request) { - checkEqualString(t, "", r.URL.Path) + checkEqualString(t, "/api/v1/query", r.URL.Path) }, }, { @@ -274,19 +263,7 @@ func TestRequestParams(t *testing.T) { appendTypePrefix: true, }, func(t *testing.T, r *http.Request) { - checkEqualString(t, prometheusPrefix+prometheusInstantPath, r.URL.Path) - }, - }, - { - "prometheus prefix with disablePathAppend", - false, - &VMStorage{ - dataSourceType: NewPrometheusType(), - appendTypePrefix: true, - disablePathAppend: true, - }, - func(t *testing.T, r *http.Request) { - checkEqualString(t, prometheusPrefix, r.URL.Path) + checkEqualString(t, "/prometheus/api/v1/query", r.URL.Path) }, }, { @@ -296,18 +273,7 @@ func TestRequestParams(t *testing.T) { dataSourceType: NewPrometheusType(), }, func(t *testing.T, r *http.Request) { - checkEqualString(t, prometheusRangePath, r.URL.Path) - }, - }, - { - "prometheus range path with disablePathAppend", - true, - &VMStorage{ - dataSourceType: NewPrometheusType(), - disablePathAppend: true, - }, - func(t *testing.T, r *http.Request) { - checkEqualString(t, "", r.URL.Path) + checkEqualString(t, "/api/v1/query_range", r.URL.Path) }, }, { @@ -318,19 +284,7 @@ func TestRequestParams(t *testing.T) { appendTypePrefix: true, }, func(t *testing.T, r *http.Request) { - checkEqualString(t, prometheusPrefix+prometheusRangePath, r.URL.Path) - }, - }, - { - "prometheus range prefix with disablePathAppend", - true, - &VMStorage{ - dataSourceType: NewPrometheusType(), - appendTypePrefix: true, - disablePathAppend: true, - }, - func(t *testing.T, r *http.Request) { - checkEqualString(t, prometheusPrefix, r.URL.Path) + checkEqualString(t, "/prometheus/api/v1/query_range", r.URL.Path) }, }, { diff --git a/app/vmalert/remoteread/init.go b/app/vmalert/remoteread/init.go index d5f9e0a4a4..1b765e1244 100644 --- a/app/vmalert/remoteread/init.go +++ b/app/vmalert/remoteread/init.go @@ -34,8 +34,6 @@ var ( oauth2ClientSecretFile = flag.String("remoteRead.oauth2.clientSecretFile", "", "Optional OAuth2 clientSecretFile to use for -remoteRead.url.") oauth2TokenURL = flag.String("remoteRead.oauth2.tokenUrl", "", "Optional OAuth2 tokenURL to use for -remoteRead.url. ") oauth2Scopes = flag.String("remoteRead.oauth2.scopes", "", "Optional OAuth2 scopes to use for -remoteRead.url. Scopes must be delimited by ';'.") - - disablePathAppend = flag.Bool("remoteRead.disablePathAppend", false, "Whether to disable automatic appending of '/api/v1/query' path to the configured -remoteRead.url.") ) // Init creates a Querier from provided flag values. @@ -57,5 +55,5 @@ func Init() (datasource.QuerierBuilder, error) { return nil, fmt.Errorf("failed to configure auth: %w", err) } c := &http.Client{Transport: tr} - return datasource.NewVMStorage(*addr, authCfg, 0, 0, false, c, *disablePathAppend), nil + return datasource.NewVMStorage(*addr, authCfg, 0, 0, false, c), nil } diff --git a/app/vmalert/remotewrite/init.go b/app/vmalert/remotewrite/init.go index 1f927f8a96..de5c0abdbd 100644 --- a/app/vmalert/remotewrite/init.go +++ b/app/vmalert/remotewrite/init.go @@ -39,8 +39,6 @@ var ( oauth2ClientSecretFile = flag.String("remoteWrite.oauth2.clientSecretFile", "", "Optional OAuth2 clientSecretFile to use for -remoteWrite.url.") oauth2TokenURL = flag.String("remoteWrite.oauth2.tokenUrl", "", "Optional OAuth2 tokenURL to use for -notifier.url.") oauth2Scopes = flag.String("remoteWrite.oauth2.scopes", "", "Optional OAuth2 scopes to use for -notifier.url. Scopes must be delimited by ';'.") - - disablePathAppend = flag.Bool("remoteWrite.disablePathAppend", false, "Whether to disable automatic appending of '/api/v1/write' path to the configured -remoteWrite.url.") ) // Init creates Client object from given flags. diff --git a/app/vmalert/remotewrite/remotewrite.go b/app/vmalert/remotewrite/remotewrite.go index 35fa56ebdf..992cea22bf 100644 --- a/app/vmalert/remotewrite/remotewrite.go +++ b/app/vmalert/remotewrite/remotewrite.go @@ -3,6 +3,7 @@ package remotewrite import ( "bytes" "context" + "flag" "fmt" "io/ioutil" "net/http" @@ -19,17 +20,20 @@ import ( "github.com/VictoriaMetrics/metrics" ) +var ( + disablePathAppend = flag.Bool("remoteWrite.disablePathAppend", false, "Whether to disable automatic appending of '/api/v1/write' path to the configured -remoteWrite.url.") +) + // Client is an asynchronous HTTP client for writing // timeseries via remote write protocol. type Client struct { - addr string - c *http.Client - authCfg *promauth.Config - input chan prompbmarshal.TimeSeries - flushInterval time.Duration - maxBatchSize int - maxQueueSize int - disablePathAppend bool + addr string + c *http.Client + authCfg *promauth.Config + input chan prompbmarshal.TimeSeries + flushInterval time.Duration + maxBatchSize int + maxQueueSize int wg sync.WaitGroup doneCh chan struct{} @@ -70,8 +74,6 @@ const ( defaultWriteTimeout = 30 * time.Second ) -const writePath = "/api/v1/write" - // NewClient returns asynchronous client for // writing timeseries via remotewrite protocol. func NewClient(ctx context.Context, cfg Config) (*Client, error) { @@ -102,14 +104,13 @@ func NewClient(ctx context.Context, cfg Config) (*Client, error) { Timeout: cfg.WriteTimeout, Transport: cfg.Transport, }, - addr: strings.TrimSuffix(cfg.Addr, "/"), - authCfg: cfg.AuthCfg, - flushInterval: cfg.FlushInterval, - maxBatchSize: cfg.MaxBatchSize, - maxQueueSize: cfg.MaxQueueSize, - doneCh: make(chan struct{}), - input: make(chan prompbmarshal.TimeSeries, cfg.MaxQueueSize), - disablePathAppend: cfg.DisablePathAppend, + addr: strings.TrimSuffix(cfg.Addr, "/"), + authCfg: cfg.AuthCfg, + flushInterval: cfg.FlushInterval, + maxBatchSize: cfg.MaxBatchSize, + maxQueueSize: cfg.MaxQueueSize, + doneCh: make(chan struct{}), + input: make(chan prompbmarshal.TimeSeries, cfg.MaxQueueSize), } for i := 0; i < cc; i++ { @@ -240,8 +241,8 @@ func (c *Client) send(ctx context.Context, data []byte) error { req.Header.Set("Authorization", auth) } } - if !c.disablePathAppend { - req.URL.Path = path.Join(req.URL.Path, writePath) + if !*disablePathAppend { + req.URL.Path = path.Join(req.URL.Path, "/api/v1/write") } resp, err := c.c.Do(req.WithContext(ctx)) if err != nil { diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5dc1b3c4e5..c5ed9a965b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -20,6 +20,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): do not return values from [label_value()](https://docs.victoriametrics.com/MetricsQL.html#label_value) function if the original time series has no values at the selected timestamps. * BUGFIX: [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): limit the number of concurrently established connections from vmselect to vmstorage. This should prevent from potentially high spikes in the number of established connections after temporary slowdown in connection handshake procedure between vmselect and vmstorage because of spikes in workload. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2552). * BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl.html): fix build for Solaris / SmartOS. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1322#issuecomment-1120276146). +* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert.html): do not add `/api/v1/query` suffix to `-datasource.url` if `-remoteRead.disablePathAppend` command-line flag is set. Previously this flag was applied only to `-remoteRead.url`, which could confuse users. ## [v1.77.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.77.1)