Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions app/vlselect/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ package vlselect
import (
"context"
"embed"
"encoding/json"
"flag"
"fmt"
"net/http"
nethttputil "net/http/httputil"
"net/url"
"strings"
"time"

"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputil"
Expand All @@ -29,6 +33,9 @@ var (

disableSelect = flag.Bool("select.disable", false, "Whether to disable /select/* HTTP endpoints")
disableInternal = flag.Bool("internalselect.disable", false, "Whether to disable /internal/select/* HTTP endpoints")

vmalertProxyURL = flag.String("vmalert.proxyURL", "", "Optional URL for proxying requests to vmalert."+
"See https://docs.victoriametrics.com/victorialogs#vmalert.")
)

func getDefaultMaxConcurrentRequests() int {
Expand All @@ -48,6 +55,8 @@ func getDefaultMaxConcurrentRequests() int {
// Init initializes vlselect
func Init() {
concurrencyLimitCh = make(chan struct{}, *maxConcurrentRequests)
initVMUIConfig()
initVMAlertProxy()
}

// Stop stops vlselect
Expand Down Expand Up @@ -111,6 +120,22 @@ func selectHandler(w http.ResponseWriter, r *http.Request, path string) bool {
return true
}
if strings.HasPrefix(path, "/select/vmui/") {
if path == "/select/vmui/config.json" {
w.Header().Set("Content-Type", "application/json")
r.URL.Path = strings.TrimPrefix(path, "/select")
if disableTenantControls := r.Header.Get("VL-Disable-Tenant-Controls"); disableTenantControls == "true" {
w.Header().Set("VL-Disable-Tenant-Controls", "true")
} else {
if accountID := r.Header.Get("AccountID"); len(accountID) > 0 {
w.Header().Set("AccountID", accountID)
}
if projectID := r.Header.Get("ProjectID"); len(projectID) > 0 {
w.Header().Set("ProjectID", projectID)
}
}
fmt.Fprint(w, vmuiConfig)
return true
}
if strings.HasPrefix(path, "/select/vmui/static/") {
// Allow clients caching static contents for long period of time, since it shouldn't change over time.
// Path to static contents (such as js and css) must be changed whenever its contents is changed.
Expand Down Expand Up @@ -212,6 +237,17 @@ func decRequestConcurrency() {
func processSelectRequest(ctx context.Context, w http.ResponseWriter, r *http.Request, path string) bool {
httpserver.EnableCORS(w, r)
startTime := time.Now()
if strings.HasPrefix(path, "/select/vmalert/") {
vmalertRequests.Inc()
if len(*vmalertProxyURL) == 0 {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", `{"status":"error","msg":"for accessing vmalert flag '-vmalert.proxyURL' must be configured"}`)
return true
}
proxyVMAlertRequests(w, r)
return true
}
switch path {
case "/select/logsql/facets":
logsqlFacetsRequests.Inc()
Expand Down Expand Up @@ -286,6 +322,72 @@ func getMaxQueryDuration(r *http.Request) time.Duration {
return d
}

func proxyVMAlertRequests(w http.ResponseWriter, r *http.Request) {
defer func() {
err := recover()
if err == nil || err == http.ErrAbortHandler {
// Suppress http.ErrAbortHandler panic.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1353
return
}
// Forward other panics to the caller.
panic(err)
}()
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/select")
r.Host = vmalertProxyHost
vmalertProxy.ServeHTTP(w, r)
}

func initVMUIConfig() {
var cfg struct {
Version string `json:"version"`
License struct {
Type string `json:"type"`
} `json:"license"`
VMAlert struct {
Enabled bool `json:"enabled"`
} `json:"vmalert"`
}
cfg.Version = buildinfo.ShortVersion()
if cfg.Version == "" {
// buildinfo.ShortVersion() may return empty result for builds without tags
cfg.Version = buildinfo.Version
}
data, err := vmuiFiles.ReadFile("vmui/config.json")
if err != nil {
logger.Fatalf("cannot read vmui default config: %s", err)
}
err = json.Unmarshal(data, &cfg)
if err != nil {
logger.Fatalf("cannot parse vmui default config: %s", err)
}
cfg.VMAlert.Enabled = len(*vmalertProxyURL) != 0
data, err = json.Marshal(&cfg)
if err != nil {
logger.Fatalf("cannot create vmui config: %s", err)
}
vmuiConfig = string(data)
}

// initVMAlertProxy must be called after flag.Parse(), since it uses command-line flags.
func initVMAlertProxy() {
if len(*vmalertProxyURL) == 0 {
return
}
proxyURL, err := url.Parse(*vmalertProxyURL)
if err != nil {
logger.Fatalf("cannot parse -vmalert.proxyURL=%q: %s", *vmalertProxyURL, err)
}
vmalertProxyHost = proxyURL.Host
vmalertProxy = nethttputil.NewSingleHostReverseProxy(proxyURL)
}

var (
vmalertProxyHost string
vmalertProxy *nethttputil.ReverseProxy
vmuiConfig string
)

var (
logsqlFacetsRequests = metrics.NewCounter(`vl_http_requests_total{path="/select/logsql/facets"}`)
logsqlFacetsDuration = metrics.NewSummary(`vl_http_request_duration_seconds{path="/select/logsql/facets"}`)
Expand Down Expand Up @@ -322,4 +424,6 @@ var (

// no need to track duration for tail requests, as they usually take long time
logsqlTailRequests = metrics.NewCounter(`vl_http_requests_total{path="/select/logsql/tail"}`)

vmalertRequests = metrics.NewCounter(`vl_http_requests_total{path="/select/vmalert"}`)
)
2 changes: 2 additions & 0 deletions docs/victorialogs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta

## tip

* FEATURE: proxy VMAlert requests at `/select/vmalert` path, when `-vmalert.proxyURL` flag is set. See [#8272](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8272).

* BUGFIX: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): allow using unquoted [pipe names](https://docs.victoriametrics.com/victorialogs/logsql/#pipes) inside [LogsQL filters](https://docs.victoriametrics.com/victorialogs/logsql/#filters). For example, `fields.foo:bar` is allowed now, while previously it should be written as `"fields.foo":bar`. See [#669](https://github.com/VictoriaMetrics/VictoriaLogs/issues/669).
* BUGFIX: properly detele unneeded directories at [Ossfs2 filesystem](https://www.alibabacloud.com/help/en/oss/developer-reference/ossfs-2-0/). See [#649](https://github.com/VictoriaMetrics/VictoriaLogs/issues/649). Thanks to @xiaozongyang for [the initial pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9709).
* BUGFIX: all [Enterprise version of VictoriaLogs](https://docs.victoriametrics.com/victoriametrics/enterprise/): fix support for automatic issuing of TLS certificates for HTTPS server via Let's Encrypt service using TLS-ALPN-01 challenge. See [Automatic issuing of TLS certificates](https://docs.victoriametrics.com/victorialogs/#automatic-issuing-of-tls-certificates) for more info.
Expand Down
7 changes: 7 additions & 0 deletions docs/victorialogs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,13 @@ The following steps must be performed for restoring the partition data from back

It is also possible to use **the disk snapshot** feature provided by the operating system or cloud provider in order to perform a backup.

## vmalert

VictoriaLogs is capable of proxying requests to [VMAlert](https://docs.victoriametrics.com/victorialogs/vmalert/)
when `-vmalert.proxyURL` flag is set. Use this feature for accessing VMAlert API through VictoriaLogs Web interface.

For accessing VMAlert API through VictoriaLogs configure `-vmalert.proxyURL` flag. All VMAlert endpoints become available at `http://<victorialogs-addr>:9428/select/vmalert`.

## Multitenancy

VictoriaLogs supports multitenancy. A tenant is identified by `(AccountID, ProjectID)` pair, where `AccountID` and `ProjectID` are arbitrary 32-bit unsigned integers.
Expand Down
3 changes: 3 additions & 0 deletions docs/victorialogs/vmalert.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ and [`/select/logsql/stats_query_range`](https://docs.victoriametrics.com/victor
These endpoints return the log stats in a format compatible with [Prometheus querying API](https://prometheus.io/docs/prometheus/latest/querying/api/#instant-queries).
It allows using VictoriaLogs as the datasource in vmalert, creating alerting and recording rules via [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/).

Configure `-vmalert.proxyURL` on [VictoriaLogs](https://docs.victoriametrics.com/victorialogs/#vmalert){{% available_from "#" %}} to proxy requests to `vmalert`.
Proxying is needed to access `vmalert`'s UI through [vmui](https://docs.victoriametrics.com/#vmui).

> This page provides only integration instructions for vmalert and VictoriaLogs. See the full textbook for vmalert [here](https://docs.victoriametrics.com/victoriametrics/vmalert/).

## Quick Start
Expand Down