mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-05-26 13:07:42 +03:00
Compare commits
42 Commits
add-tests-
...
issue-8229
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c157576c2f | ||
|
|
b1e998f7ad | ||
|
|
171d4019cd | ||
|
|
54f60d804a | ||
|
|
78dc9533fc | ||
|
|
088e06c2c2 | ||
|
|
553e95e293 | ||
|
|
46fbb95b16 | ||
|
|
fbe592f495 | ||
|
|
631b736bc2 | ||
|
|
ceefa406cc | ||
|
|
2748681f40 | ||
|
|
e2cfd351c0 | ||
|
|
a2b49a1843 | ||
|
|
a70e8e0379 | ||
|
|
894a2f91e6 | ||
|
|
30af662d84 | ||
|
|
fa2107bbec | ||
|
|
1427ea3ca9 | ||
|
|
5561970db0 | ||
|
|
4d42e29967 | ||
|
|
72837919ae | ||
|
|
6166149474 | ||
|
|
f34e82eb9b | ||
|
|
2545082c0f | ||
|
|
676669020f | ||
|
|
071db473a7 | ||
|
|
94ac051647 | ||
|
|
3419c56eef | ||
|
|
3091133a36 | ||
|
|
63a1baf10f | ||
|
|
64a3c13c2f | ||
|
|
0b801a147e | ||
|
|
a45afa4cd8 | ||
|
|
552f0ce466 | ||
|
|
f3012c4a85 | ||
|
|
2589065329 | ||
|
|
777f05efcc | ||
|
|
03a1883525 | ||
|
|
17fd53bd37 | ||
|
|
34204cc597 | ||
|
|
e22d47b85c |
@@ -2,6 +2,7 @@ package notifier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -27,10 +28,12 @@ func TestBlackHoleNotifier_Send(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlackHoleNotifier_Close(t *testing.T) {
|
||||
addr := "blackhole-close"
|
||||
bh := newBlackHoleNotifier()
|
||||
bh.addr = addr
|
||||
if err := bh.Send(context.Background(), []Alert{{
|
||||
GroupID: 0,
|
||||
Name: "alert0",
|
||||
Name: "alert1",
|
||||
Start: time.Now().UTC(),
|
||||
End: time.Now().UTC(),
|
||||
Annotations: map[string]string{"a": "b", "c": "d", "e": "f"},
|
||||
@@ -41,10 +44,10 @@ func TestBlackHoleNotifier_Close(t *testing.T) {
|
||||
bh.Close()
|
||||
|
||||
defaultMetrics := metricset.GetDefaultSet()
|
||||
alertMetricName := "vmalert_alerts_sent_total{addr=\"blackhole\"}"
|
||||
alertMetricName := fmt.Sprintf("vmalert_alerts_sent_total{addr=%q}", addr)
|
||||
for _, name := range defaultMetrics.ListMetricNames() {
|
||||
if name == alertMetricName {
|
||||
t.Fatalf("Metric name should have unregistered.But still present")
|
||||
t.Fatalf("Metric name should have unregistered. But still present")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ var (
|
||||
|
||||
maxQueueSize = flag.Int("remoteWrite.maxQueueSize", defaultMaxQueueSize, "Defines the max number of pending datapoints to remote write endpoint")
|
||||
maxBatchSize = flag.Int("remoteWrite.maxBatchSize", defaultMaxBatchSize, "Defines max number of timeseries to be flushed at once")
|
||||
concurrency = flag.Int("remoteWrite.concurrency", defaultConcurrency, "Defines number of writers for concurrent writing into remote write endpoint")
|
||||
concurrency = flag.Int("remoteWrite.concurrency", defaultConcurrency, "Defines number of writers for concurrent writing into remote write endpoint. Default value depends on the number of available CPU cores.")
|
||||
flushInterval = flag.Duration("remoteWrite.flushInterval", defaultFlushInterval, "Defines interval of flushes to remote write endpoint")
|
||||
|
||||
tlsInsecureSkipVerify = flag.Bool("remoteWrite.tlsInsecureSkipVerify", false, "Whether to skip tls verification when connecting to -remoteWrite.url")
|
||||
|
||||
@@ -1,14 +1,56 @@
|
||||
package utils
|
||||
|
||||
import "github.com/VictoriaMetrics/metrics"
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
)
|
||||
|
||||
type namedMetric struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
var usedMetrics map[string]*atomic.Int64
|
||||
var usedMetricMu sync.Mutex
|
||||
|
||||
func trackUsedMetric(name string) {
|
||||
usedMetricMu.Lock()
|
||||
defer usedMetricMu.Unlock()
|
||||
|
||||
if usedMetrics == nil {
|
||||
usedMetrics = make(map[string]*atomic.Int64)
|
||||
}
|
||||
if _, ok := usedMetrics[name]; !ok {
|
||||
usedMetrics[name] = &atomic.Int64{}
|
||||
}
|
||||
usedMetrics[name].Add(1)
|
||||
}
|
||||
|
||||
// Unregister removes the metric by name from default registry
|
||||
func (nm namedMetric) Unregister() {
|
||||
metrics.UnregisterMetric(nm.Name)
|
||||
if usedMetrics == nil {
|
||||
logger.Fatalf("BUG: unregistered metric %q before registering", nm.Name)
|
||||
}
|
||||
|
||||
usedMetricMu.Lock()
|
||||
counter, ok := usedMetrics[nm.Name]
|
||||
if !ok {
|
||||
logger.Fatalf("BUG: unregistered metric %q before registering", nm.Name)
|
||||
}
|
||||
current := counter.Add(-1)
|
||||
usedMetricMu.Unlock()
|
||||
|
||||
if current < 0 {
|
||||
logger.Fatalf("BUG: negative metric counter for %q", nm.Name)
|
||||
}
|
||||
|
||||
if current == 0 {
|
||||
metrics.UnregisterMetric(nm.Name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Gauge is a metrics.Gauge with Name
|
||||
@@ -19,6 +61,7 @@ type Gauge struct {
|
||||
|
||||
// GetOrCreateGauge creates a new Gauge with the given name
|
||||
func GetOrCreateGauge(name string, f func() float64) *Gauge {
|
||||
trackUsedMetric(name)
|
||||
return &Gauge{
|
||||
namedMetric: namedMetric{Name: name},
|
||||
Gauge: metrics.GetOrCreateGauge(name, f),
|
||||
@@ -33,6 +76,7 @@ type Counter struct {
|
||||
|
||||
// GetOrCreateCounter creates a new Counter with the given name
|
||||
func GetOrCreateCounter(name string) *Counter {
|
||||
trackUsedMetric(name)
|
||||
return &Counter{
|
||||
namedMetric: namedMetric{Name: name},
|
||||
Counter: metrics.GetOrCreateCounter(name),
|
||||
@@ -47,6 +91,7 @@ type Summary struct {
|
||||
|
||||
// GetOrCreateSummary creates a new Summary with the given name
|
||||
func GetOrCreateSummary(name string) *Summary {
|
||||
trackUsedMetric(name)
|
||||
return &Summary{
|
||||
namedMetric: namedMetric{Name: name},
|
||||
Summary: metrics.GetOrCreateSummary(name),
|
||||
|
||||
52
app/vmalert/utils/metrics_test.go
Normal file
52
app/vmalert/utils/metrics_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
)
|
||||
|
||||
func isMetricRegistered(name string) bool {
|
||||
metricNames := metrics.GetDefaultSet().ListMetricNames()
|
||||
for _, mn := range metricNames {
|
||||
if mn == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func TestMetricIsUnregistered(t *testing.T) {
|
||||
metricName := "example_runs_total"
|
||||
c := GetOrCreateCounter(metricName)
|
||||
if !isMetricRegistered(metricName) {
|
||||
t.Errorf("Expected metric %s to be present", metricName)
|
||||
}
|
||||
|
||||
c.Unregister()
|
||||
if isMetricRegistered(metricName) {
|
||||
t.Errorf("Expected metric %s to be unregistered", metricName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricIsRemovedIfNoUses(t *testing.T) {
|
||||
metricName := "example_runs_total"
|
||||
c := GetOrCreateCounter(metricName)
|
||||
c2 := GetOrCreateCounter(metricName)
|
||||
|
||||
if !isMetricRegistered(metricName) {
|
||||
t.Errorf("Expected metric %s to be present", metricName)
|
||||
}
|
||||
|
||||
c.Unregister()
|
||||
// metric should still be registered since c2 is using it
|
||||
if !isMetricRegistered(metricName) {
|
||||
t.Errorf("Expected metric %s to be present", metricName)
|
||||
}
|
||||
|
||||
c2.Unregister()
|
||||
if isMetricRegistered(metricName) {
|
||||
t.Errorf("Expected metric %s to be unregistered", metricName)
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
httpListenAddrs = flagutil.NewArrayString("httpListenAddr", "TCP address to listen for incoming http requests. See also -tls and -httpListenAddr.useProxyProtocol")
|
||||
httpListenAddrs = flagutil.NewArrayString("httpListenAddr", "TCP address to listen for incoming http requests. "+
|
||||
"By default, serves internal API and proxy requests. "+
|
||||
" See also -tls, -httpListenAddr.useProxyProtocol and -httpInternalListenAddr.")
|
||||
httpInternalListenAddr = flagutil.NewArrayString("httpInternalListenAddr", "TCP address to listen for incoming internal API http requests. Such as /health, /-/reload, /debug/pprof, etc. "+
|
||||
"If flag is set, vmauth no longer serves internal API at -httpListenAddr.")
|
||||
useProxyProtocol = flagutil.NewArrayBool("httpListenAddr.useProxyProtocol", "Whether to use proxy protocol for connections accepted at the corresponding -httpListenAddr . "+
|
||||
"See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt . "+
|
||||
"With enabled proxy protocol http server cannot serve regular /metrics endpoint. Use -pushmetrics.url for metrics pushing")
|
||||
@@ -91,7 +95,21 @@ func main() {
|
||||
logger.Infof("starting vmauth at %q...", listenAddrs)
|
||||
startTime := time.Now()
|
||||
initAuthConfig()
|
||||
go httpserver.Serve(listenAddrs, useProxyProtocol, requestHandler)
|
||||
disableInternalRoutes := len(*httpInternalListenAddr) > 0
|
||||
rh := requestHandlerWithInternalRoutes
|
||||
if disableInternalRoutes {
|
||||
rh = requestHandler
|
||||
}
|
||||
|
||||
serveOpts := httpserver.ServeOptions{
|
||||
UseProxyProtocol: useProxyProtocol,
|
||||
DisableBuiltinRoutes: disableInternalRoutes,
|
||||
}
|
||||
go httpserver.ServeWithOpts(listenAddrs, rh, serveOpts)
|
||||
|
||||
if len(*httpInternalListenAddr) > 0 {
|
||||
go httpserver.Serve(*httpInternalListenAddr, nil, internalRequestHandler)
|
||||
}
|
||||
logger.Infof("started vmauth in %.3f seconds", time.Since(startTime).Seconds())
|
||||
|
||||
pushmetrics.Init()
|
||||
@@ -109,7 +127,7 @@ func main() {
|
||||
logger.Infof("successfully stopped vmauth in %.3f seconds", time.Since(startTime).Seconds())
|
||||
}
|
||||
|
||||
func requestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
func internalRequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
switch r.URL.Path {
|
||||
case "/-/reload":
|
||||
if !httpserver.CheckAuthFlag(w, r, reloadAuthKey) {
|
||||
@@ -120,6 +138,17 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func requestHandlerWithInternalRoutes(w http.ResponseWriter, r *http.Request) bool {
|
||||
if internalRequestHandler(w, r) {
|
||||
return true
|
||||
}
|
||||
return requestHandler(w, r)
|
||||
}
|
||||
|
||||
func requestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
|
||||
ats := getAuthTokensFromRequest(r)
|
||||
if len(ats) == 0 {
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestRequestHandler(t *testing.T) {
|
||||
r.Header.Set("Pass-Header", "abc")
|
||||
|
||||
w := &fakeResponseWriter{}
|
||||
if !requestHandler(w, r) {
|
||||
if !requestHandlerWithInternalRoutes(w, r) {
|
||||
t.Fatalf("unexpected false is returned from requestHandler")
|
||||
}
|
||||
|
||||
|
||||
@@ -596,7 +596,8 @@ var (
|
||||
&cli.Int64Flag{
|
||||
Name: vmRateLimit,
|
||||
Usage: "Optional data transfer rate limit in bytes per second.\n" +
|
||||
"By default, the rate limit is disabled. It can be useful for limiting load on source or destination databases.",
|
||||
"By default, the rate limit is disabled. It can be useful for limiting load on source or destination databases. \n" +
|
||||
"Rate limit is applied per worker, see `--vm-concurrency`.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: vmInterCluster,
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputils"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/memory"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/netutil"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/querytracer"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
|
||||
)
|
||||
@@ -142,10 +143,13 @@ func FederateHandler(startTime time.Time, w http.ResponseWriter, r *http.Request
|
||||
WriteFederate(bb, rs)
|
||||
return sw.maybeFlushBuffer(bb)
|
||||
})
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
err = sw.flush()
|
||||
}
|
||||
if err != nil && !netutil.IsTrivialNetworkError(err) {
|
||||
return fmt.Errorf("error during sending data to remote client: %w", err)
|
||||
}
|
||||
return sw.flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
var federateDuration = metrics.NewSummary(`vm_request_duration_seconds{path="/federate"}`)
|
||||
@@ -226,10 +230,13 @@ func ExportCSVHandler(startTime time.Time, w http.ResponseWriter, r *http.Reques
|
||||
}()
|
||||
}
|
||||
err = <-doneCh
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
err = sw.flush()
|
||||
}
|
||||
if err != nil && !netutil.IsTrivialNetworkError(err) {
|
||||
return fmt.Errorf("error during sending the exported csv data to remote client: %w", err)
|
||||
}
|
||||
return sw.flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
var exportCSVDuration = metrics.NewSummary(`vm_request_duration_seconds{path="/api/v1/export/csv"}`)
|
||||
@@ -281,10 +288,13 @@ func ExportNativeHandler(startTime time.Time, w http.ResponseWriter, r *http.Req
|
||||
bb.B = dst
|
||||
return sw.maybeFlushBuffer(bb)
|
||||
})
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
err = sw.flush()
|
||||
}
|
||||
if err != nil && !netutil.IsTrivialNetworkError(err) {
|
||||
return fmt.Errorf("error during sending native data to remote client: %w", err)
|
||||
}
|
||||
return sw.flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
var exportNativeDuration = metrics.NewSummary(`vm_request_duration_seconds{path="/api/v1/export/native"}`)
|
||||
@@ -441,16 +451,19 @@ func exportHandler(qt *querytracer.Tracer, w http.ResponseWriter, cp *commonPara
|
||||
}()
|
||||
}
|
||||
err := <-doneCh
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
err = sw.flush()
|
||||
}
|
||||
if err == nil {
|
||||
if format == "promapi" {
|
||||
WriteExportPromAPIFooter(bw, qt)
|
||||
}
|
||||
err = bw.Flush()
|
||||
}
|
||||
if err != nil && !netutil.IsTrivialNetworkError(err) {
|
||||
return fmt.Errorf("cannot send data to remote client: %w", err)
|
||||
}
|
||||
if err := sw.flush(); err != nil {
|
||||
return fmt.Errorf("cannot send data to remote client: %w", err)
|
||||
}
|
||||
if format == "promapi" {
|
||||
WriteExportPromAPIFooter(bw, qt)
|
||||
}
|
||||
return bw.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
type exportBlock struct {
|
||||
|
||||
@@ -483,8 +483,11 @@ func binaryOpOr(bfa *binaryOpFuncArg) ([]*timeseries, error) {
|
||||
mLeft, mRight := createTimeseriesMapByTagSet(bfa.be, bfa.left, bfa.right)
|
||||
var rvs []*timeseries
|
||||
|
||||
for _, tss := range mLeft {
|
||||
rvs = append(rvs, tss...)
|
||||
for k, tss := range mLeft {
|
||||
tssLeft := removeEmptySeries(tss)
|
||||
// re-assign modified slice to map, since it can be referred later
|
||||
mLeft[k] = tssLeft
|
||||
rvs = append(rvs, tssLeft...)
|
||||
}
|
||||
// Sort left-hand-side series by metric name as Prometheus does.
|
||||
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5393
|
||||
@@ -497,7 +500,10 @@ func binaryOpOr(bfa *binaryOpFuncArg) ([]*timeseries, error) {
|
||||
rvs = append(rvs, tssRight...)
|
||||
continue
|
||||
}
|
||||
fillLeftNaNsWithRightValues(tssLeft, tssRight)
|
||||
fillLeftNaNsWithRightValuesOrMerge(tssLeft, tssRight)
|
||||
// tssRight might be filled with NaNs after merge
|
||||
tssRight = removeEmptySeries(tssRight)
|
||||
rvs = append(rvs, tssRight...)
|
||||
}
|
||||
// Sort the added right-hand-side series by metric name as Prometheus does.
|
||||
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5393
|
||||
@@ -526,6 +532,35 @@ func fillLeftNaNsWithRightValues(tssLeft, tssRight []*timeseries) {
|
||||
}
|
||||
}
|
||||
|
||||
// fill gaps in tssLeft with values from tssRight when labels match
|
||||
// Set NaNs to tssRight when tssLeft has corresponding values
|
||||
// or if tssLeft and tssRight can be merged.
|
||||
//
|
||||
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7759
|
||||
// https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7640
|
||||
func fillLeftNaNsWithRightValuesOrMerge(tssLeft, tssRight []*timeseries) {
|
||||
for _, tsLeft := range tssLeft {
|
||||
valuesLeft := tsLeft.Values
|
||||
nameLeft := tsLeft.MetricName.String()
|
||||
for i, v := range valuesLeft {
|
||||
leftIsNaN := math.IsNaN(v)
|
||||
for _, tsRight := range tssRight {
|
||||
canBeMerged := nameLeft == tsRight.MetricName.String()
|
||||
valueRight := tsRight.Values[i]
|
||||
if leftIsNaN && canBeMerged {
|
||||
// fill NaNs with valueRight if labels match
|
||||
valuesLeft[i] = valueRight
|
||||
}
|
||||
if !leftIsNaN || canBeMerged {
|
||||
// set NaN to valueRight if valueLeft is not NaN
|
||||
// or if left and right can be merged
|
||||
tsRight.Values[i] = nan
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func binaryOpIfnot(bfa *binaryOpFuncArg) ([]*timeseries, error) {
|
||||
mLeft, mRight := createTimeseriesMapByTagSet(bfa.be, bfa.left, bfa.right)
|
||||
var rvs []*timeseries
|
||||
|
||||
@@ -4461,9 +4461,9 @@ func TestExecSuccess(t *testing.T) {
|
||||
t.Run(`histogram_quantile(nan-bucket-count-some)`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
q := `round(histogram_quantile(0.6,
|
||||
label_set(90, "foo", "bar", "le", "10")
|
||||
or label_set(NaN, "foo", "bar", "le", "30")
|
||||
or label_set(300, "foo", "bar", "le", "+Inf")
|
||||
union(label_set(90, "foo", "bar", "le", "10"),
|
||||
label_set(NaN, "foo", "bar", "le", "30"),
|
||||
label_set(300, "foo", "bar", "le", "+Inf"))
|
||||
),0.01)`
|
||||
r := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
@@ -9409,7 +9409,384 @@ func TestExecSuccess(t *testing.T) {
|
||||
resultExpected := []netstorage.Result{r}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`nan or on() series`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// left side returns NaNs only, so the right side should replace its values and labels
|
||||
// https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7759
|
||||
q := `(label_set(1, "a", "a", "b", "b1") == 0) or on(a) label_set(2, "a", "a", "b", "b2")`
|
||||
r := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{2, 2, 2, 2, 2, 2},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b2"),
|
||||
}}
|
||||
resultExpected := []netstorage.Result{r}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series with NaNs or scalar`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
q := `(label_set(time() >= 1600, "a", "a", "b", "b1")) or 1`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b1"),
|
||||
}}
|
||||
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1, 1, 1, 1, 1, 1},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series or on() scalar`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7640
|
||||
q := `(label_set(time() > 1200, "a", "a", "b", "b1")) or on() vector(0)`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, 1400, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b1"),
|
||||
}}
|
||||
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{0, 0, nan, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series or on() series`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// left side + right side
|
||||
q := `(label_set(time() <= 1200, "a", "a", "b", "b1")) or on(a) label_set(time() > 1200, "a", "a", "b", "b2")`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, 1200, nan, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b1"),
|
||||
}}
|
||||
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, 1400, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b2"),
|
||||
}}
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series with no NaNs or on() series`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// left side contains all needed values, so the right side should be dropped
|
||||
q := `(label_set(time() < 3000, "a", "a", "b", "b1")) or on(a) label_set(time() > 3000, "a", "a", "b", "b2")`
|
||||
r := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, 1200, 1400, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b1"),
|
||||
}}
|
||||
|
||||
resultExpected := []netstorage.Result{r}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series or on() series with overlap`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// left overlap with right
|
||||
q := `(label_set(time() <= 1500, "a", "a", "b", "b1")) or on(a) label_set(time() > 1100, "a", "a", "b", "b2")`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, 1200, 1400, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b1"),
|
||||
}}
|
||||
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b2"),
|
||||
}}
|
||||
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series or on() series merge`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// left + right for same series
|
||||
q := `(label_set(time() <= 1200, "a", "a", "b", "b1")) or on(a) label_set(time() > 1400, "a", "a", "b", "b1")`
|
||||
r := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, 1200, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("a"),
|
||||
Value: []byte("a"),
|
||||
}, {
|
||||
Key: []byte("b"),
|
||||
Value: []byte("b1"),
|
||||
}}
|
||||
|
||||
resultExpected := []netstorage.Result{r}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`scalar or timeseries`, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
q := `time() > 1400 or label_set(123, "foo", "bar")`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{123, 123, 123, 123, 123, 123},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{{
|
||||
Key: []byte("foo"),
|
||||
Value: []byte("bar"),
|
||||
}}
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`series or many series`, func(t *testing.T) {
|
||||
//load 1m
|
||||
// foo{a="a", b="1"} 1 0 1 1 1
|
||||
// bar{a="a", b="2"} 2 2 2 2 2
|
||||
// bar{a="a", b="3"} 3 3 3 3 3
|
||||
//
|
||||
//eval range from 0 to 4m step 1m foo!=0 or on (a) bar
|
||||
// foo{a="a", b="1"} 1 _ 1 1 1
|
||||
// bar{a="a", b="2"} _ 2 _ _ _
|
||||
// bar{a="a", b="3"} _ 3 _ _ _
|
||||
// https://github.com/prometheus/prometheus/tree/main/promql/promqltest
|
||||
t.Parallel()
|
||||
q := `(
|
||||
label_set(time()!=1200, "x", "foo"),
|
||||
) or on(x) (
|
||||
label_set(time()+1, "x", "foo", "y", "bar"),
|
||||
label_set(time()+2, "y", "baz", "x", "foo"),
|
||||
)`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, nan, 1400, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("x"), Value: []byte("foo")},
|
||||
}
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, 1201, nan, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("x"), Value: []byte("foo")},
|
||||
{Key: []byte("y"), Value: []byte("bar")},
|
||||
}
|
||||
r3 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, 1202, nan, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r3.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("x"), Value: []byte("foo")},
|
||||
{Key: []byte("y"), Value: []byte("baz")},
|
||||
}
|
||||
resultExpected := []netstorage.Result{r1, r2, r3}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`many series or series`, func(t *testing.T) {
|
||||
//load 1m
|
||||
// foo{a="a", b="1"} 1 0 1 1 1
|
||||
// foo{a="a", b="2"} 2 2 2 2 2
|
||||
// bar{a="a", b="3"} 3 3 3 3 3
|
||||
//
|
||||
//eval range from 0 to 4m step 1m foo!=0 or on (a) bar
|
||||
// foo{a="a", b="1"} 1 _ 1 1 1
|
||||
// foo{a="a", b="2"} 2 2 2 2 2
|
||||
// https://github.com/prometheus/prometheus/tree/main/promql/promqltest
|
||||
t.Parallel()
|
||||
q := `(
|
||||
label_set(time()!=1200, "x", "foo"),
|
||||
label_set(time()+1, "x", "foo", "y","baz"),
|
||||
) or on(x) (
|
||||
label_set(time()+2, "x", "foo", "y", "bar"),
|
||||
)`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, nan, 1400, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("x"), Value: []byte("foo")},
|
||||
}
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1001, 1201, 1401, 1601, 1801, 2001},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("x"), Value: []byte("foo")},
|
||||
{Key: []byte("y"), Value: []byte("baz")},
|
||||
}
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`many series or series with no merge`, func(t *testing.T) {
|
||||
// load 1m
|
||||
// foo{job="a1", a="a"} 0 0 1 1 0
|
||||
// foo{job="a2", a="a"} 1 1 0 0 0
|
||||
// foo{job="a3", a="a"} 1 1 1 1 1
|
||||
// foo{job="a4", a="a"} 1 1 1 1 1
|
||||
//
|
||||
//eval range from 0 to 4m step 1m (foo{job=~"a1|a2"} == 0) or on (a) (foo{job=~"a3|a4"} == 1)
|
||||
// foo{job="a1", a="a"} 0 0 _ _ 0
|
||||
// foo{job="a2", a="a"} _ _ 0 0 0
|
||||
// https://github.com/prometheus/prometheus/tree/main/promql/promqltest
|
||||
t.Parallel()
|
||||
q := `(
|
||||
label_set(time()!=1400, "job", "a1", "a", "a"),
|
||||
label_set(time()>=1400, "job", "a2", "a", "a"),
|
||||
) or on(a) (
|
||||
label_set(time(), "job", "a3", "a", "a"),
|
||||
label_set(time(), "job", "a4", "a", "a"),
|
||||
)`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, 1200, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("a"), Value: []byte("a")},
|
||||
{Key: []byte("job"), Value: []byte("a1")},
|
||||
}
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, 1400, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("a"), Value: []byte("a")},
|
||||
{Key: []byte("job"), Value: []byte("a2")},
|
||||
}
|
||||
resultExpected := []netstorage.Result{r1, r2}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
t.Run(`many series or series with merge`, func(t *testing.T) {
|
||||
// load 1m
|
||||
// foo{job="a1", a="a"} 0 0 1 1 0
|
||||
// foo{job="a2", a="a"} 1 1 1 0 0
|
||||
// foo{job="a3", a="a"} 1 1 1 1 1
|
||||
// foo{job="a4", a="a"} 1 1 1 1 1
|
||||
//
|
||||
//eval range from 0 to 4m step 1m (foo{job=~"a1|a2"} == 0) or on (a) (foo{job=~"a3|a4"} == 1)
|
||||
// foo{job="a1", a="a"} 0 0 _ _ 0
|
||||
// foo{job="a2", a="a"} _ _ _ 0 0
|
||||
// foo{job="a3", a="a"} _ _ 1 _ _
|
||||
// foo{job="a4", a="a"} _ _ 1 _ _
|
||||
// https://github.com/prometheus/prometheus/tree/main/promql/promqltest
|
||||
t.Parallel()
|
||||
q := `(
|
||||
label_set(time()!=1400, "job", "a1", "a", "a"),
|
||||
label_set(time()>=1600, "job", "a2", "a", "a"),
|
||||
) or on(a) (
|
||||
label_set(time(), "job", "a3", "a", "a"),
|
||||
label_set(time(), "job", "a4", "a", "a"),
|
||||
)`
|
||||
r1 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{1000, 1200, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r1.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("a"), Value: []byte("a")},
|
||||
{Key: []byte("job"), Value: []byte("a1")},
|
||||
}
|
||||
r2 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, nan, 1600, 1800, 2000},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r2.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("a"), Value: []byte("a")},
|
||||
{Key: []byte("job"), Value: []byte("a2")},
|
||||
}
|
||||
r3 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, 1400, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r3.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("a"), Value: []byte("a")},
|
||||
{Key: []byte("job"), Value: []byte("a3")},
|
||||
}
|
||||
r4 := netstorage.Result{
|
||||
MetricName: metricNameExpected,
|
||||
Values: []float64{nan, nan, 1400, nan, nan, nan},
|
||||
Timestamps: timestampsExpected,
|
||||
}
|
||||
r4.MetricName.Tags = []storage.Tag{
|
||||
{Key: []byte("a"), Value: []byte("a")},
|
||||
{Key: []byte("job"), Value: []byte("a4")},
|
||||
}
|
||||
resultExpected := []netstorage.Result{r1, r2, r3, r4}
|
||||
f(q, resultExpected)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExecError(t *testing.T) {
|
||||
|
||||
@@ -99,7 +99,8 @@ func TestParseMetricSelectorSuccess(t *testing.T) {
|
||||
f(`{foo="bar"}`)
|
||||
f(`{:f:oo=~"bar.+"}`)
|
||||
f(`foo {bar != "baz"}`)
|
||||
f(` foo { bar !~ "^ddd(x+)$", a="ss", __name__="sffd"} `)
|
||||
f(` { bar !~ "^ddd(x+)$", a="ss", __name__="sffd"} `)
|
||||
f(` { bar !~ "^ddd(x+)$", a="ss", "foo"} `)
|
||||
f(`(foo)`)
|
||||
f(`\п\р\и\в\е\т{\ы="111"}`)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export interface Logs {
|
||||
export interface LogHits {
|
||||
timestamps: string[];
|
||||
values: number[];
|
||||
total?: number;
|
||||
total: number;
|
||||
fields: { [key: string]: string; };
|
||||
_isOther: boolean;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ const BarHitsTooltip: FC<Props> = ({ data, focusDataIdx, uPlotInst }) => {
|
||||
</div>
|
||||
)}
|
||||
<div className="vm-chart-tooltip-header">
|
||||
<div className="vm-chart-tooltip-header__title">
|
||||
<div className="vm-chart-tooltip-header__title vm-bar-hits-tooltip__date">
|
||||
{tooltipData.timestamp}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,4 +24,8 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&__date {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ const useBarHitsOptions = ({
|
||||
width: strokeWidth[graphOptions.graphStyle],
|
||||
spanGaps: true,
|
||||
stroke: color,
|
||||
fill: graphOptions.fill ? color + "80" : "",
|
||||
fill: graphOptions.fill ? color + (target?._isOther ? "" : "80") : "",
|
||||
paths: getSeriesPaths(graphOptions.graphStyle),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -36,35 +36,40 @@ const AxesLimitsConfigurator: FC<AxesLimitsConfiguratorProps> = ({ yaxis, setYax
|
||||
"vm-axes-limits_mobile": isMobile
|
||||
})}
|
||||
>
|
||||
<Switch
|
||||
value={yaxis.limits.enable}
|
||||
onChange={toggleEnableLimits}
|
||||
label="Fix the limits for y-axis"
|
||||
fullWidth={isMobile}
|
||||
/>
|
||||
<div className="vm-axes-limits-list">
|
||||
{axes.map(axis => (
|
||||
<div
|
||||
className="vm-axes-limits-list__inputs"
|
||||
key={axis}
|
||||
>
|
||||
<TextField
|
||||
label={`Min ${axis}`}
|
||||
type="number"
|
||||
disabled={!yaxis.limits.enable}
|
||||
value={yaxis.limits.range[axis][0]}
|
||||
onChange={createHandlerOnchangeAxis(axis, 0)}
|
||||
/>
|
||||
<TextField
|
||||
label={`Max ${axis}`}
|
||||
type="number"
|
||||
disabled={!yaxis.limits.enable}
|
||||
value={yaxis.limits.range[axis][1]}
|
||||
onChange={createHandlerOnchangeAxis(axis, 1)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<div className="vm-graph-settings-row">
|
||||
<span className="vm-graph-settings-row__label">Fixed Y-axis limits</span>
|
||||
<Switch
|
||||
value={yaxis.limits.enable}
|
||||
onChange={toggleEnableLimits}
|
||||
label={`${yaxis.limits.enable ? "Fixed" : "Auto"} limits`}
|
||||
fullWidth={isMobile}
|
||||
/>
|
||||
</div>
|
||||
{yaxis.limits.enable && (
|
||||
<div className="vm-axes-limits-list">
|
||||
{axes.map(axis => (
|
||||
<div
|
||||
className="vm-axes-limits-list__inputs"
|
||||
key={axis}
|
||||
>
|
||||
<TextField
|
||||
label={`Min ${axis}`}
|
||||
type="number"
|
||||
disabled={!yaxis.limits.enable}
|
||||
value={yaxis.limits.range[axis][0]}
|
||||
onChange={createHandlerOnchangeAxis(axis, 0)}
|
||||
/>
|
||||
<TextField
|
||||
label={`Max ${axis}`}
|
||||
type="number"
|
||||
disabled={!yaxis.limits.enable}
|
||||
value={yaxis.limits.range[axis][1]}
|
||||
onChange={createHandlerOnchangeAxis(axis, 1)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,10 +8,14 @@ import "./style.scss";
|
||||
import Tooltip from "../../Main/Tooltip/Tooltip";
|
||||
import useBoolean from "../../../hooks/useBoolean";
|
||||
import LinesConfigurator from "./LinesConfigurator/LinesConfigurator";
|
||||
import GraphTypeSwitcher from "./GraphTypeSwitcher/GraphTypeSwitcher";
|
||||
import { MetricResult } from "../../../api/types";
|
||||
import { isHistogramData } from "../../../utils/metric";
|
||||
|
||||
const title = "Graph settings";
|
||||
|
||||
interface GraphSettingsProps {
|
||||
data: MetricResult[],
|
||||
yaxis: YaxisState,
|
||||
setYaxisLimits: (limits: AxisRange) => void,
|
||||
toggleEnableLimits: () => void,
|
||||
@@ -19,11 +23,13 @@ interface GraphSettingsProps {
|
||||
value: boolean,
|
||||
onChange: (value: boolean) => void,
|
||||
},
|
||||
isHistogram?: boolean,
|
||||
}
|
||||
|
||||
const GraphSettings: FC<GraphSettingsProps> = ({ yaxis, setYaxisLimits, toggleEnableLimits, spanGaps }) => {
|
||||
const GraphSettings: FC<GraphSettingsProps> = ({ data, yaxis, setYaxisLimits, toggleEnableLimits, spanGaps }) => {
|
||||
const popperRef = useRef<HTMLDivElement>(null);
|
||||
const buttonRef = useRef<HTMLDivElement>(null);
|
||||
const displayHistogramMode = isHistogramData(data);
|
||||
|
||||
const {
|
||||
value: openPopper,
|
||||
@@ -64,6 +70,7 @@ const GraphSettings: FC<GraphSettingsProps> = ({ yaxis, setYaxisLimits, toggleEn
|
||||
spanGaps={spanGaps.value}
|
||||
onChange={spanGaps.onChange}
|
||||
/>
|
||||
{displayHistogramMode && <GraphTypeSwitcher onChange={handleClose}/>}
|
||||
</div>
|
||||
</div>
|
||||
</Popper>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React, { FC } from "preact/compat";
|
||||
import Switch from "../../../Main/Switch/Switch";
|
||||
import useDeviceDetect from "../../../../hooks/useDeviceDetect";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { useChangeDisplayMode } from "./useChangeDisplayMode";
|
||||
|
||||
type Props = {
|
||||
onChange: () => void;
|
||||
}
|
||||
|
||||
const GraphTypeSwitcher: FC<Props> = ({ onChange }) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
|
||||
const { handleChange } = useChangeDisplayMode();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const value = !searchParams.get("display_mode");
|
||||
|
||||
const handleChangeMode = (val: boolean) => {
|
||||
handleChange(val, onChange);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="vm-graph-settings-row">
|
||||
<span className="vm-graph-settings-row__label">Histogram mode</span>
|
||||
<Switch
|
||||
value={value}
|
||||
onChange={handleChangeMode}
|
||||
label={value ? "Enabled" : "Disabled"}
|
||||
fullWidth={isMobile}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GraphTypeSwitcher;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { useTimeDispatch } from "../../../../state/time/TimeStateContext";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
|
||||
export const useChangeDisplayMode = () => {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const dispatch = useTimeDispatch();
|
||||
|
||||
const handleChange = (val: boolean, callback?: () => void) => {
|
||||
val ? searchParams.delete("display_mode") : searchParams.set("display_mode", "lines");
|
||||
setSearchParams(searchParams);
|
||||
dispatch({ type: "RUN_QUERY" });
|
||||
callback && callback();
|
||||
};
|
||||
|
||||
return { handleChange };
|
||||
};
|
||||
@@ -10,14 +10,17 @@ interface Props {
|
||||
const LinesConfigurator: FC<Props> = ({ spanGaps, onChange }) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
|
||||
return <div>
|
||||
<Switch
|
||||
value={spanGaps}
|
||||
onChange={onChange}
|
||||
label="Connect null values"
|
||||
fullWidth={isMobile}
|
||||
/>
|
||||
</div>;
|
||||
return (
|
||||
<div className="vm-graph-settings-row">
|
||||
<span className="vm-graph-settings-row__label">Connect null values</span>
|
||||
<Switch
|
||||
value={spanGaps}
|
||||
onChange={onChange}
|
||||
label={spanGaps ? "Enabled" : "Disabled"}
|
||||
fullWidth={isMobile}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LinesConfigurator;
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
@use "src/styles/variables" as *;
|
||||
|
||||
.vm-graph-settings {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $padding-small;
|
||||
|
||||
&-popper {
|
||||
display: grid;
|
||||
gap: $padding-global;
|
||||
padding: 0 0 $padding-global;
|
||||
padding: $padding-small $padding-large $padding-large;
|
||||
min-width: 300px;
|
||||
|
||||
&__body {
|
||||
display: grid;
|
||||
gap: $padding-large;
|
||||
padding: 0 $padding-global;
|
||||
}
|
||||
}
|
||||
|
||||
&-row {
|
||||
display: grid;
|
||||
gap: $padding-small;
|
||||
grid-template-columns: minmax(150px, max-content) 1fr;
|
||||
|
||||
&__label {
|
||||
&:after{
|
||||
content: ":";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ const GroupLogsConfigurators: FC<Props> = ({ logs }) => {
|
||||
const noWrapLines = searchParams.get(NO_WRAP_LINES) === "true";
|
||||
const compactGroupHeader = searchParams.get(COMPACT_GROUP_HEADER) === "true";
|
||||
const displayFieldsString = searchParams.get(DISPLAY_FIELDS) || "";
|
||||
const displayFields = displayFieldsString ? displayFieldsString.split(",") : [];
|
||||
const displayFields = displayFieldsString ? displayFieldsString.split(",") : [LOGS_DISPLAY_FIELDS];
|
||||
|
||||
const [dateFormat, setDateFormat] = useState(searchParams.get(DATE_FORMAT) || LOGS_DATE_FORMAT);
|
||||
const [errorFormat, setErrorFormat] = useState("");
|
||||
|
||||
const isGroupChanged = groupBy !== LOGS_GROUP_BY;
|
||||
const isDisplayFieldsChanged = displayFields.length > 0;
|
||||
const isDisplayFieldsChanged = displayFields.length !== 1 || displayFields[0] !== LOGS_DISPLAY_FIELDS;
|
||||
const isTimeChanged = searchParams.get(DATE_FORMAT) !== LOGS_DATE_FORMAT;
|
||||
const hasChanges = [
|
||||
isGroupChanged,
|
||||
@@ -58,9 +58,7 @@ const GroupLogsConfigurators: FC<Props> = ({ logs }) => {
|
||||
].some(Boolean);
|
||||
|
||||
const logsKeys = useMemo(() => {
|
||||
const excludeKeys = ["_msg", "_time"];
|
||||
const uniqKeys = Array.from(new Set(logs.map(l => Object.keys(l)).flat()));
|
||||
return uniqKeys.filter(k => !excludeKeys.includes(k));
|
||||
return Array.from(new Set(logs.map(l => Object.keys(l)).flat()));
|
||||
}, [logs]);
|
||||
|
||||
const {
|
||||
|
||||
@@ -4,13 +4,16 @@ import { useState } from "react";
|
||||
import Tooltip from "../Tooltip/Tooltip";
|
||||
import Button from "../Button/Button";
|
||||
import { CopyIcon } from "../Icons";
|
||||
import useCopyToClipboard from "../../../hooks/useCopyToClipboard";
|
||||
|
||||
enum CopyState { copy = "Copy", copied = "Copied" }
|
||||
|
||||
const CodeExample: FC<{code: string}> = ({ code }) => {
|
||||
const copyToClipboard = useCopyToClipboard();
|
||||
|
||||
const [tooltip, setTooltip] = useState(CopyState.copy);
|
||||
const handlerCopy = () => {
|
||||
navigator.clipboard.writeText(code);
|
||||
const handlerCopy = async () => {
|
||||
await copyToClipboard(code);
|
||||
setTooltip(CopyState.copied);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
border-radius: $border-radius-small;
|
||||
|
||||
&_open {
|
||||
z-index: 100;
|
||||
z-index: 101;
|
||||
opacity: 1;
|
||||
transform-origin: top center;
|
||||
animation: vm-slider 150ms cubic-bezier(0.280, 0.840, 0.420, 1.1);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getComparator, stableSort } from "./helpers";
|
||||
import Tooltip from "../Main/Tooltip/Tooltip";
|
||||
import Button from "../Main/Button/Button";
|
||||
import { useEffect } from "preact/compat";
|
||||
import useCopyToClipboard from "../../hooks/useCopyToClipboard";
|
||||
|
||||
type OrderDir = "asc" | "desc"
|
||||
|
||||
@@ -22,6 +23,8 @@ interface TableProps<T> {
|
||||
}
|
||||
|
||||
const Table = <T extends object>({ rows, columns, defaultOrderBy, defaultOrderDir, copyToClipboard, paginationOffset }: TableProps<T>) => {
|
||||
const handleCopyToClipboard = useCopyToClipboard();
|
||||
|
||||
const [orderBy, setOrderBy] = useState<keyof T>(defaultOrderBy);
|
||||
const [orderDir, setOrderDir] = useState<OrderDir>(defaultOrderDir || "desc");
|
||||
const [copied, setCopied] = useState<number | null>(null);
|
||||
@@ -42,7 +45,7 @@ const Table = <T extends object>({ rows, columns, defaultOrderBy, defaultOrderDi
|
||||
const createCopyHandler = (copyValue: string | number, rowIndex: number) => async () => {
|
||||
if (copied === rowIndex) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(String(copyValue));
|
||||
await handleCopyToClipboard(String(copyValue));
|
||||
setCopied(rowIndex);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
@@ -26,6 +26,7 @@ import useElementSize from "../../../hooks/useElementSize";
|
||||
import { ChartTooltipProps } from "../../Chart/ChartTooltip/ChartTooltip";
|
||||
import LegendAnomaly from "../../Chart/Line/LegendAnomaly/LegendAnomaly";
|
||||
import { groupByMultipleKeys } from "../../../utils/array";
|
||||
import { useGraphDispatch } from "../../../state/graph/GraphStateContext";
|
||||
|
||||
export interface GraphViewProps {
|
||||
data?: MetricResult[];
|
||||
@@ -62,6 +63,8 @@ const GraphView: FC<GraphViewProps> = ({
|
||||
isAnomalyView,
|
||||
spanGaps
|
||||
}) => {
|
||||
const graphDispatch = useGraphDispatch();
|
||||
|
||||
const { isMobile } = useDeviceDetect();
|
||||
const { timezone } = useTimeState();
|
||||
const currentStep = useMemo(() => customStep || period.step || "1s", [period.step, customStep]);
|
||||
@@ -196,6 +199,26 @@ const GraphView: FC<GraphViewProps> = ({
|
||||
|
||||
const [containerRef, containerSize] = useElementSize();
|
||||
|
||||
const hasTimeData = dataChart[0]?.length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
const checkEmptyHistogram = () => {
|
||||
if (!isHistogram || !data[1]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const values = (dataChart?.[1]?.[2] || []) as (number | null)[];
|
||||
return values.every(v => v === null);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const isEmpty = checkEmptyHistogram();
|
||||
graphDispatch({ type: "SET_IS_EMPTY_HISTOGRAM", payload: isEmpty });
|
||||
}, [dataChart, isHistogram]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames({
|
||||
@@ -205,7 +228,7 @@ const GraphView: FC<GraphViewProps> = ({
|
||||
})}
|
||||
ref={containerRef}
|
||||
>
|
||||
{!isHistogram && (
|
||||
{!isHistogram && hasTimeData && (
|
||||
<LineChart
|
||||
data={dataChart}
|
||||
series={series}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { isHistogramData } from "../utils/metric";
|
||||
import { useGraphState } from "../state/graph/GraphStateContext";
|
||||
import { getStepFromDuration } from "../utils/time";
|
||||
import { AppType } from "../types/appType";
|
||||
import { getQueryStringValue } from "../utils/query-string";
|
||||
|
||||
interface FetchQueryParams {
|
||||
predefinedQuery?: string[]
|
||||
@@ -132,7 +133,8 @@ export const useFetchQuery = ({
|
||||
tempTraces.push(trace);
|
||||
}
|
||||
|
||||
isHistogramResult = !isAnomalyUI && isDisplayChart && isHistogramData(resp.data.result);
|
||||
const preventChangeType = !!getQueryStringValue("display_mode", null);
|
||||
isHistogramResult = !isAnomalyUI && isDisplayChart && !preventChangeType && isHistogramData(resp.data.result);
|
||||
seriesLimit = isHistogramResult ? Infinity : defaultLimit;
|
||||
const freeTempSize = seriesLimit - tempData.length;
|
||||
resp.data.result.slice(0, freeTempSize).forEach((d: MetricBase) => {
|
||||
|
||||
@@ -47,7 +47,9 @@ const GraphTab: FC<Props> = ({ isHistogram, graphData, controlsRef, isAnomalyVie
|
||||
<div className="vm-custom-panel-body-header__graph-controls">
|
||||
<GraphTips/>
|
||||
<GraphSettings
|
||||
data={graphData}
|
||||
yaxis={yaxis}
|
||||
isHistogram={isHistogram}
|
||||
setYaxisLimits={setYaxisLimits}
|
||||
toggleEnableLimits={toggleEnableLimits}
|
||||
spanGaps={{ value: spanGaps, onChange: setSpanGaps }}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import React, { FC } from "preact/compat";
|
||||
import Alert from "../../../components/Main/Alert/Alert";
|
||||
import { useGraphState } from "../../../state/graph/GraphStateContext";
|
||||
import {
|
||||
useChangeDisplayMode
|
||||
} from "../../../components/Configurators/GraphSettings/GraphTypeSwitcher/useChangeDisplayMode";
|
||||
import Button from "../../../components/Main/Button/Button";
|
||||
import "./style.scss";
|
||||
|
||||
const WarningHeatmapToLine:FC = () => {
|
||||
const { isEmptyHistogram } = useGraphState();
|
||||
const { handleChange } = useChangeDisplayMode();
|
||||
|
||||
if (!isEmptyHistogram) return null;
|
||||
|
||||
return (
|
||||
<Alert variant="warning">
|
||||
<div className="vm-warning-heatmap-to-line">
|
||||
<p className="vm-warning-heatmap-to-line__text">
|
||||
The expression cannot be displayed as a heatmap.
|
||||
To make the graph work, disable the heatmap in the "Graph settings" or modify the expression.
|
||||
</p>
|
||||
|
||||
<Button
|
||||
size="small"
|
||||
color="primary"
|
||||
variant="text"
|
||||
onClick={() => handleChange(false)}
|
||||
>
|
||||
Switch to line chart
|
||||
</Button>
|
||||
</div>
|
||||
</Alert>
|
||||
);
|
||||
};
|
||||
|
||||
export default WarningHeatmapToLine;
|
||||
@@ -0,0 +1,7 @@
|
||||
@use "src/styles/variables" as *;
|
||||
|
||||
.vm-warning-heatmap-to-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import WarningLimitSeries from "./WarningLimitSeries/WarningLimitSeries";
|
||||
import CustomPanelTabs from "./CustomPanelTabs";
|
||||
import { DisplayType } from "../../types";
|
||||
import DownloadReport from "./DownloadReport/DownloadReport";
|
||||
import WarningHeatmapToLine from "./WarningHeatmapToLine/WarningHeatmapToLine";
|
||||
|
||||
const CustomPanel: FC = () => {
|
||||
useSetQueryParams();
|
||||
@@ -93,6 +94,7 @@ const CustomPanel: FC = () => {
|
||||
/>
|
||||
{showError && <Alert variant="error">{error}</Alert>}
|
||||
{showInstantQueryTip && <Alert variant="info"><InstantQueryTip/></Alert>}
|
||||
<WarningHeatmapToLine/>
|
||||
{warning && (
|
||||
<WarningLimitSeries
|
||||
warning={warning}
|
||||
|
||||
@@ -40,7 +40,7 @@ const GroupLogsItem: FC<Props> = ({ log, displayFields = ["_msg"] }) => {
|
||||
return marked(log._msg.replace(/```/g, "\n```\n")) as string;
|
||||
}, [log._msg, markdownParsing]);
|
||||
|
||||
const fields = useMemo(() => Object.entries(log).filter(([key]) => key !== "_msg"), [log]);
|
||||
const fields = useMemo(() => Object.entries(log), [log]);
|
||||
const hasFields = fields.length > 0;
|
||||
|
||||
const displayMessage = useMemo(() => {
|
||||
|
||||
@@ -66,7 +66,7 @@ export const useFetchLogHits = (server: string, query: string) => {
|
||||
setError(error);
|
||||
}
|
||||
|
||||
setLogHits(hits.map(hit => ({ ...hit, _isOther: isEmptyObject(hit.fields) })));
|
||||
setLogHits(hits.map(markIsOther).sort(sortHits));
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.name !== "AbortError") {
|
||||
setError(String(e));
|
||||
@@ -85,3 +85,18 @@ export const useFetchLogHits = (server: string, query: string) => {
|
||||
abortController: abortControllerRef.current
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Helper function to check if a hit is "other"
|
||||
const markIsOther = (hit: LogHits) => ({
|
||||
...hit,
|
||||
_isOther: isEmptyObject(hit.fields)
|
||||
});
|
||||
|
||||
// Comparison function for sorting hits
|
||||
const sortHits = (a: LogHits, b: LogHits) => {
|
||||
if (a._isOther !== b._isOther) {
|
||||
return a._isOther ? -1 : 1; // "Other" hits first to avoid graph overlap
|
||||
}
|
||||
return b.total - a.total; // Sort remaining by total for better visibility
|
||||
};
|
||||
|
||||
@@ -119,6 +119,7 @@ const PredefinedPanel: FC<PredefinedPanelsProps> = ({
|
||||
{title || ""}
|
||||
</h3>
|
||||
<GraphSettings
|
||||
data={graphData || []}
|
||||
yaxis={yaxis}
|
||||
setYaxisLimits={setYaxisLimits}
|
||||
toggleEnableLimits={toggleEnableLimits}
|
||||
|
||||
@@ -20,6 +20,8 @@ import TableSettings from "../../../components/Table/TableSettings/TableSettings
|
||||
import { getColumns } from "../../../hooks/useSortedCategories";
|
||||
import { useCustomPanelDispatch, useCustomPanelState } from "../../../state/customPanel/CustomPanelStateContext";
|
||||
import TableView from "../../../components/Views/TableView/TableView";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import WarningHeatmapToLine from "../../CustomPanel/WarningHeatmapToLine/WarningHeatmapToLine";
|
||||
|
||||
type Props = {
|
||||
data: DataAnalyzerType[];
|
||||
@@ -28,6 +30,8 @@ type Props = {
|
||||
|
||||
const QueryAnalyzerView: FC<Props> = ({ data, period }) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const { tableCompact } = useCustomPanelState();
|
||||
const customPanelDispatch = useCustomPanelDispatch();
|
||||
|
||||
@@ -101,11 +105,16 @@ const QueryAnalyzerView: FC<Props> = ({ data, period }) => {
|
||||
setQueries(tempQueries);
|
||||
setGraphData(tempGraphData);
|
||||
setLiveData(tempLiveData);
|
||||
|
||||
// reset display mode
|
||||
searchParams.delete("display_mode");
|
||||
setSearchParams(searchParams);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsHistogram(!!graphData && isHistogramData(graphData));
|
||||
}, [graphData]);
|
||||
const noSpecificDisplayMode = !searchParams.get("display_mode");
|
||||
setIsHistogram(!!graphData && noSpecificDisplayMode && isHistogramData(graphData));
|
||||
}, [graphData, searchParams]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -120,6 +129,7 @@ const QueryAnalyzerView: FC<Props> = ({ data, period }) => {
|
||||
onDeleteClick={handleTraceDelete}
|
||||
/>
|
||||
)}
|
||||
<WarningHeatmapToLine/>
|
||||
<div
|
||||
className={classNames({
|
||||
"vm-block": true,
|
||||
@@ -138,7 +148,9 @@ const QueryAnalyzerView: FC<Props> = ({ data, period }) => {
|
||||
{displayType === "chart" && <GraphTips/>}
|
||||
{displayType === "chart" && (
|
||||
<GraphSettings
|
||||
data={graphData || []}
|
||||
yaxis={yaxis}
|
||||
isHistogram={isHistogram}
|
||||
setYaxisLimits={setYaxisLimits}
|
||||
toggleEnableLimits={toggleEnableLimits}
|
||||
spanGaps={{ value: spanGaps, onChange: setSpanGaps }}
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface GraphState {
|
||||
customStep: string
|
||||
yaxis: YaxisState
|
||||
isHistogram: boolean
|
||||
isEmptyHistogram: boolean
|
||||
/** when true, null data values will not cause line breaks */
|
||||
spanGaps: boolean
|
||||
}
|
||||
@@ -24,6 +25,7 @@ export type GraphAction =
|
||||
| { type: "SET_YAXIS_LIMITS", payload: AxisRange }
|
||||
| { type: "SET_CUSTOM_STEP", payload: string}
|
||||
| { type: "SET_IS_HISTOGRAM", payload: boolean }
|
||||
| { type: "SET_IS_EMPTY_HISTOGRAM", payload: boolean }
|
||||
| { type: "SET_SPAN_GAPS", payload: boolean }
|
||||
|
||||
export const initialGraphState: GraphState = {
|
||||
@@ -32,6 +34,7 @@ export const initialGraphState: GraphState = {
|
||||
limits: { enable: false, range: { "1": [0, 0] } }
|
||||
},
|
||||
isHistogram: false,
|
||||
isEmptyHistogram: false,
|
||||
spanGaps: false,
|
||||
};
|
||||
|
||||
@@ -69,6 +72,11 @@ export function reducer(state: GraphState, action: GraphAction): GraphState {
|
||||
...state,
|
||||
isHistogram: action.payload
|
||||
};
|
||||
case "SET_IS_EMPTY_HISTOGRAM":
|
||||
return {
|
||||
...state,
|
||||
isEmptyHistogram: action.payload
|
||||
};
|
||||
case "SET_SPAN_GAPS":
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -153,7 +153,10 @@ export const normalizeData = (buckets: MetricResult[], isHistogram?: boolean): M
|
||||
const totalHitsPerTimestamp: { [timestamp: number]: number } = {};
|
||||
vmBuckets.forEach(bucket =>
|
||||
bucket.values.forEach(([timestamp, value]) => {
|
||||
totalHitsPerTimestamp[timestamp] = (totalHitsPerTimestamp[timestamp] || 0) + +value;
|
||||
const valueNum = Number(value);
|
||||
const number = isNaN(valueNum) ? 0 : valueNum;
|
||||
const prevTotal = totalHitsPerTimestamp[timestamp] || 0;
|
||||
totalHitsPerTimestamp[timestamp] = prevTotal + number;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package apptest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -134,6 +136,23 @@ func (c *vmcluster) ForceFlush(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// MustStartVmauth is a test helper function that starts an instance of
|
||||
// vmauth and fails the test if the app fails to start.
|
||||
func (tc *TestCase) MustStartVmauth(instance string, flags []string, configFileYAML string) *Vmauth {
|
||||
tc.t.Helper()
|
||||
|
||||
configFilePath := path.Join(tc.t.TempDir(), "config.yaml")
|
||||
if err := os.WriteFile(configFilePath, []byte(configFileYAML), os.ModePerm); err != nil {
|
||||
tc.t.Fatalf("cannot init vmauth: config file write failed: %s", err)
|
||||
}
|
||||
app, err := StartVmauth(instance, flags, tc.cli, configFilePath)
|
||||
if err != nil {
|
||||
tc.t.Fatalf("Could not start %s: %v", instance, err)
|
||||
}
|
||||
tc.addApp(instance, app)
|
||||
return app
|
||||
}
|
||||
|
||||
// MustStartDefaultCluster starts a typical cluster configuration with default
|
||||
// flags.
|
||||
func (tc *TestCase) MustStartDefaultCluster() PrometheusWriteQuerier {
|
||||
|
||||
182
apptest/tests/vmauth_routing_test.go
Normal file
182
apptest/tests/vmauth_routing_test.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/apptest"
|
||||
)
|
||||
|
||||
func TestVMAuthRouterWithAuth(t *testing.T) {
|
||||
tc := apptest.NewTestCase(t)
|
||||
defer tc.Stop()
|
||||
|
||||
var authorizedRequestsCount, unauthorizedRequestsCount int
|
||||
backendWithAuth := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {
|
||||
authorizedRequestsCount++
|
||||
}))
|
||||
defer backendWithAuth.Close()
|
||||
backend := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {
|
||||
unauthorizedRequestsCount++
|
||||
}))
|
||||
defer backend.Close()
|
||||
|
||||
authConfig := fmt.Sprintf(`
|
||||
users:
|
||||
- name: user1
|
||||
username: ba-username
|
||||
password: ba-password
|
||||
url_prefix: %s
|
||||
unauthorized_user:
|
||||
url_map:
|
||||
- src_paths:
|
||||
- /backend/health
|
||||
- /backend/ready
|
||||
url_prefix: %s
|
||||
`, backendWithAuth.URL, backend.URL)
|
||||
|
||||
vmauth := tc.MustStartVmauth("vmauth", nil, authConfig)
|
||||
|
||||
makeGetRequestExpectCode := func(prepareRequest func(*http.Request), expectCode int) {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("http://%s", vmauth.GetHTTPListenAddr()), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot build http.Request: %s", err)
|
||||
}
|
||||
prepareRequest(req)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot make http.Get request for target=%q: %s", req.URL, err)
|
||||
}
|
||||
responseText, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot read response body: %s", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != expectCode {
|
||||
t.Fatalf("unexpected http response code: %d, want: %d, response text: %s", resp.StatusCode, expectCode, responseText)
|
||||
}
|
||||
}
|
||||
assertBackendsRequestsCount := func(expectAuthorized, expectUnauthorized int) {
|
||||
t.Helper()
|
||||
if expectAuthorized != authorizedRequestsCount {
|
||||
t.Fatalf("expected to have %d authorized proxied requests, got: %d", expectAuthorized, authorizedRequestsCount)
|
||||
}
|
||||
|
||||
if expectUnauthorized != unauthorizedRequestsCount {
|
||||
t.Fatalf("expected to have %d unauthorized proxied requests, got: %d", expectUnauthorized, unauthorizedRequestsCount)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
makeGetRequestExpectCode(func(r *http.Request) {
|
||||
r.URL.Path = "/backend/api"
|
||||
r.URL.User = url.UserPassword("ba-username", "ba-password")
|
||||
}, http.StatusOK)
|
||||
assertBackendsRequestsCount(1, 0)
|
||||
|
||||
makeGetRequestExpectCode(func(r *http.Request) {
|
||||
r.URL.Path = "/backend/health"
|
||||
}, http.StatusOK)
|
||||
assertBackendsRequestsCount(1, 1)
|
||||
|
||||
// remove unauthorized section and proxy only specified path for authorized
|
||||
vmauth.UpdateConfiguration(t, fmt.Sprintf(`
|
||||
users:
|
||||
- name: user1
|
||||
username: ba-username
|
||||
password: ba-password
|
||||
url_map:
|
||||
- src_paths:
|
||||
- /backend/health
|
||||
url_prefix: %s
|
||||
`, backendWithAuth.URL))
|
||||
|
||||
// ensure unauthorized requests no longer served
|
||||
makeGetRequestExpectCode(func(r *http.Request) {
|
||||
r.URL.Path = "/backend/health"
|
||||
}, http.StatusUnauthorized)
|
||||
assertBackendsRequestsCount(1, 1)
|
||||
|
||||
makeGetRequestExpectCode(func(r *http.Request) {
|
||||
r.URL.User = url.UserPassword("ba-username", "ba-password")
|
||||
r.URL.Path = "/backend/health"
|
||||
}, http.StatusOK)
|
||||
assertBackendsRequestsCount(2, 1)
|
||||
|
||||
// url path is missing at proxy configuration
|
||||
makeGetRequestExpectCode(func(r *http.Request) {
|
||||
r.URL.User = url.UserPassword("ba-username", "ba-password")
|
||||
r.URL.Path = "/backend"
|
||||
}, http.StatusBadRequest)
|
||||
assertBackendsRequestsCount(2, 1)
|
||||
|
||||
}
|
||||
|
||||
func TestVMAuthRouterWithInternalAddr(t *testing.T) {
|
||||
tc := apptest.NewTestCase(t)
|
||||
defer tc.Stop()
|
||||
|
||||
var proxiedRequestsCount int
|
||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
proxiedRequestsCount++
|
||||
}))
|
||||
defer backend.Close()
|
||||
|
||||
authConfig := fmt.Sprintf(`
|
||||
unauthorized_user:
|
||||
url_prefix: %s
|
||||
`, backend.URL)
|
||||
|
||||
const (
|
||||
// it's not possible to use random ports
|
||||
// since it makes test flaky
|
||||
listenPortPublic = "50127"
|
||||
listenPortPrivate = "50126"
|
||||
)
|
||||
|
||||
vmauthFlags := []string{
|
||||
fmt.Sprintf("-httpListenAddr=127.0.0.1:%s", listenPortPublic),
|
||||
fmt.Sprintf("-httpInternalListenAddr=127.0.0.1:%s", listenPortPrivate),
|
||||
"-flagsAuthKey=protected",
|
||||
}
|
||||
vmauth := tc.MustStartVmauth("vmauth", vmauthFlags, authConfig)
|
||||
|
||||
makeGetRequestExpectCode := func(targetURL string, expectCode int) {
|
||||
t.Helper()
|
||||
resp, err := http.Get(targetURL)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot make http.Get request for target=%q: %s", targetURL, err)
|
||||
}
|
||||
responseText, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot read response body: %s", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != expectCode {
|
||||
t.Fatalf("unexpected http response code: %d, want: %d, response text: %s", resp.StatusCode, expectCode, responseText)
|
||||
}
|
||||
}
|
||||
assertBackendRequestsCount := func(expected int) {
|
||||
t.Helper()
|
||||
if proxiedRequestsCount != expected {
|
||||
t.Fatalf("expected to have %d proxied requests, got: %d", expected, proxiedRequestsCount)
|
||||
}
|
||||
}
|
||||
// built-in http server must reject request, since it protected with authKey
|
||||
makeGetRequestExpectCode(fmt.Sprintf("http://127.0.0.1:%s/flags", listenPortPrivate), http.StatusUnauthorized)
|
||||
assertBackendRequestsCount(0)
|
||||
|
||||
makeGetRequestExpectCode(fmt.Sprintf("http://127.0.0.1:%s/flags", listenPortPublic), http.StatusOK)
|
||||
assertBackendRequestsCount(1)
|
||||
|
||||
// reload config and ensure that vmauth no longer proxies requests to the backend
|
||||
vmauth.UpdateConfiguration(t, "")
|
||||
makeGetRequestExpectCode(fmt.Sprintf("http://127.0.0.1:%s/flags", listenPortPrivate), http.StatusUnauthorized)
|
||||
assertBackendRequestsCount(1)
|
||||
}
|
||||
82
apptest/vmauth.go
Normal file
82
apptest/vmauth.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package apptest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var httpBuilitinListenAddrRE = regexp.MustCompile(`pprof handlers are exposed at http://(.*:\d{1,5})/debug/pprof/`)
|
||||
|
||||
// Vmauth holds the state of a vmauth app and provides vmauth-specific
|
||||
// functions.
|
||||
type Vmauth struct {
|
||||
*app
|
||||
*ServesMetrics
|
||||
|
||||
httpListenAddr string
|
||||
configFilePath string
|
||||
cli *Client
|
||||
}
|
||||
|
||||
// StartVmauth starts an instance of vmauth with the given flags. It also
|
||||
// sets the default flags and populates the app instance state with runtime
|
||||
// values extracted from the application log (such as httpListenAddr)
|
||||
func StartVmauth(instance string, flags []string, cli *Client, configFilePath string) (*Vmauth, error) {
|
||||
extractREs := []*regexp.Regexp{
|
||||
httpBuilitinListenAddrRE,
|
||||
}
|
||||
|
||||
app, stderrExtracts, err := startApp(instance, "../../bin/vmauth", flags, &appOptions{
|
||||
defaultFlags: map[string]string{
|
||||
"-httpListenAddr": "127.0.0.1:0",
|
||||
"-auth.config": configFilePath,
|
||||
},
|
||||
extractREs: extractREs,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Vmauth{
|
||||
app: app,
|
||||
ServesMetrics: &ServesMetrics{
|
||||
metricsURL: fmt.Sprintf("http://%s/metrics", stderrExtracts[0]),
|
||||
cli: cli,
|
||||
},
|
||||
httpListenAddr: stderrExtracts[0],
|
||||
configFilePath: configFilePath,
|
||||
cli: cli,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateConfiguration performs configuration file reload for app and waits for configuration apply
|
||||
//
|
||||
// Due to second prescision of config reload metric, config cannot be reloaded more than 1 time in a second
|
||||
func (app *Vmauth) UpdateConfiguration(t *testing.T, configFileYAML string) {
|
||||
t.Helper()
|
||||
ct := int(time.Now().Unix())
|
||||
if err := os.WriteFile(app.configFilePath, []byte(configFileYAML), os.ModePerm); err != nil {
|
||||
t.Fatalf("unexpected error at UpdateConfiguration, cannot write configFile content: %s", err)
|
||||
}
|
||||
if err := app.process.Signal(syscall.SIGHUP); err != nil {
|
||||
t.Fatalf("unexpected signal error: %s", err)
|
||||
}
|
||||
for range 10 {
|
||||
ts := app.GetIntMetric(t, "vmauth_config_last_reload_success_timestamp_seconds")
|
||||
if ts < ct {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
t.Fatalf("timeout waiting for config reload success")
|
||||
}
|
||||
|
||||
// GetHTTPListenAddr returns listen http addr
|
||||
func (app *Vmauth) GetHTTPListenAddr() string {
|
||||
return app.httpListenAddr
|
||||
}
|
||||
@@ -3167,7 +3167,7 @@
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "The percentage of slow inserts comparing to total insertion rate during the last 5 minutes. \n\nThe less value is better. If percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \n\nIn general, VictoriaMetrics requires ~1KB or RAM per active time series, so it should be easy calculating the required amounts of RAM for the current workload according to capacity planning docs. But the resulting number may be far from the real number because the required amounts of memory depends on many other factors such as the number of labels per time series and the length of label values. See also [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"description": "The percentage of [slow inserts](https://docs.victoriametrics.com/faq/#what-is-a-slow-insert) compared to the total ingestion rate. \\n\\nThe lower the better. \\n\\nIn short, slow insert is a cache miss. There are following reasons for slow inserts to go up: \\n* Ingestion of completely new, not seen before time series;\\n* [Re-routing](https://docs.victoriametrics.com/cluster-victoriametrics/#cluster-availability) of series when one or more vmstorage nodes are unavailable;\\n* Not enough memory to maintain big enough caches for the current workload.\\n\\nIf percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \\n\\nSee [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
||||
@@ -3448,7 +3448,7 @@
|
||||
"type": "prometheus",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "The percentage of slow inserts comparing to total insertion rate during the last 5 minutes. \n\nThe less value is better. If percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \n\nIn general, VictoriaMetrics requires ~1KB or RAM per active time series, so it should be easy calculating the required amounts of RAM for the current workload according to capacity planning docs. But the resulting number may be far from the real number because the required amounts of memory depends on many other factors such as the number of labels per time series and the length of label values. See also [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"description": "The percentage of [slow inserts](https://docs.victoriametrics.com/faq/#what-is-a-slow-insert) compared to the total ingestion rate. \\n\\nThe lower the better. \\n\\nIn short, slow insert is a cache miss. There are following reasons for slow inserts to go up: \\n* Ingestion of completely new, not seen before time series;\\n* Not enough memory to maintain big enough caches for the current workload.\\n\\nIf percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \\n\\nSee [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
||||
@@ -3168,7 +3168,7 @@
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "The percentage of slow inserts comparing to total insertion rate during the last 5 minutes. \n\nThe less value is better. If percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \n\nIn general, VictoriaMetrics requires ~1KB or RAM per active time series, so it should be easy calculating the required amounts of RAM for the current workload according to capacity planning docs. But the resulting number may be far from the real number because the required amounts of memory depends on many other factors such as the number of labels per time series and the length of label values. See also [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"description": "The percentage of [slow inserts](https://docs.victoriametrics.com/faq/#what-is-a-slow-insert) compared to the total ingestion rate. \\n\\nThe lower the better. \\n\\nIn short, slow insert is a cache miss. There are following reasons for slow inserts to go up: \\n* Ingestion of completely new, not seen before time series;\\n* [Re-routing](https://docs.victoriametrics.com/cluster-victoriametrics/#cluster-availability) of series when one or more vmstorage nodes are unavailable;\\n* Not enough memory to maintain big enough caches for the current workload.\\n\\nIf percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \\n\\nSee [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
||||
@@ -3449,7 +3449,7 @@
|
||||
"type": "victoriametrics-metrics-datasource",
|
||||
"uid": "$ds"
|
||||
},
|
||||
"description": "The percentage of slow inserts comparing to total insertion rate during the last 5 minutes. \n\nThe less value is better. If percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \n\nIn general, VictoriaMetrics requires ~1KB or RAM per active time series, so it should be easy calculating the required amounts of RAM for the current workload according to capacity planning docs. But the resulting number may be far from the real number because the required amounts of memory depends on many other factors such as the number of labels per time series and the length of label values. See also [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"description": "The percentage of [slow inserts](https://docs.victoriametrics.com/faq/#what-is-a-slow-insert) compared to the total ingestion rate. \\n\\nThe lower the better. \\n\\nIn short, slow insert is a cache miss. There are following reasons for slow inserts to go up: \\n* Ingestion of completely new, not seen before time series;\\n* Not enough memory to maintain big enough caches for the current workload.\\n\\nIf percentage remains high (>10%) during extended periods of time, then it is likely more RAM is needed for optimal handling of the current number of [active time series](https://docs.victoriametrics.com/faq/#what-is-an-active-time-series). \\n\\nSee [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3976#issuecomment-1476883183) for details.",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
||||
@@ -181,7 +181,7 @@ make docker-victorialogs-up
|
||||
```
|
||||
|
||||
VictoriaLogs will be accessible on the `--httpListenAddr=:9428` port.
|
||||
In addition to VictoriaLogs server, the docker compose contains the following componetns:
|
||||
In addition to VictoriaLogs server, the docker compose contains the following components:
|
||||
* [vector](https://vector.dev/guides/) service for collecting docker logs and sending them to VictoriaLogs;
|
||||
* VictoriaMetrics single server to collect metrics from `VictoriaLogs` and `vector`;
|
||||
* [grafana](#grafana) is configured with [VictoriaLogs datasource](https://github.com/VictoriaMetrics/victorialogs-datasource).
|
||||
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
# Grafana instance configured with VictoriaMetrics as datasource
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:10.4.2
|
||||
image: grafana/grafana:11.5.0
|
||||
depends_on:
|
||||
- "vmauth"
|
||||
ports:
|
||||
|
||||
@@ -2,7 +2,7 @@ services:
|
||||
# Grafana instance configured with VictoriaLogs as datasource
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:10.4.2
|
||||
image: grafana/grafana:11.5.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
- "victorialogs"
|
||||
@@ -16,8 +16,7 @@ services:
|
||||
- ./../../dashboards/victoriametrics.json:/var/lib/grafana/dashboards/vm.json
|
||||
- ./../../dashboards/victorialogs.json:/var/lib/grafana/dashboards/vl.json
|
||||
environment:
|
||||
- "GF_INSTALL_PLUGINS=https://github.com/VictoriaMetrics/victorialogs-datasource/releases/download/v0.13.4/victoriametrics-logs-datasource-v0.13.4.zip;victoriametrics-logs-datasource"
|
||||
- "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=victoriametrics-logs-datasource"
|
||||
- "GF_INSTALL_PLUGINS=victoriametrics-logs-datasource"
|
||||
networks:
|
||||
- vm_net
|
||||
restart: always
|
||||
|
||||
@@ -46,7 +46,7 @@ services:
|
||||
# Grafana instance configured with VictoriaMetrics as datasource
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:10.4.2
|
||||
image: grafana/grafana:11.5.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
|
||||
@@ -80,8 +80,9 @@ groups:
|
||||
summary: "Remote write connection from \"{{ $labels.job }}\" (instance {{ $labels.instance }}) to {{ $labels.url }} is saturated"
|
||||
description: "The remote write connection between vmagent \"{{ $labels.job }}\" (instance {{ $labels.instance }}) and destination \"{{ $labels.url }}\"
|
||||
is saturated by more than 90% and vmagent won't be able to keep up.\n
|
||||
This usually means that `-remoteWrite.queues` command-line flag must be increased in order to increase
|
||||
the number of connections per each remote storage."
|
||||
There could be the following reasons for this:\n
|
||||
* vmagent can't send data fast enough through the existing network connections. Increase `-remoteWrite.queues` cmd-line flag value to establish more connections per destination.\n
|
||||
* remote destination can't accept data fast enough. Check if remote destination has enough resources for processing."
|
||||
|
||||
- alert: PersistentQueueForWritesIsSaturated
|
||||
expr: rate(vm_persistentqueue_write_duration_seconds_total[5m]) > 0.9
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
services:
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:10.4.2
|
||||
image: grafana/grafana:11.5.0
|
||||
depends_on:
|
||||
- "vmauth"
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- grafanadata:/var/lib/grafana
|
||||
- ./provisioning/datasources/victoriametrics-datasource/cluster.yml:/etc/grafana/provisioning/datasources/cluster.yml
|
||||
- ./provisioning/datasources/victoriametrics-metrics-datasource/cluster.yml:/etc/grafana/provisioning/datasources/cluster.yml
|
||||
- ./provisioning/dashboards:/etc/grafana/provisioning/dashboards
|
||||
- ./provisioning/plugins/:/var/lib/grafana/plugins
|
||||
- ./../../dashboards/vm/victoriametrics-cluster.json:/var/lib/grafana/dashboards/vm.json
|
||||
- ./../../dashboards/vm/vmagent.json:/var/lib/grafana/dashboards/vmagent.json
|
||||
- ./../../dashboards/vm/vmalert.json:/var/lib/grafana/dashboards/vmalert.json
|
||||
- ./../../dashboards/vm/vmauth.json:/var/lib/grafana/dashboards/vmauth.json
|
||||
environment:
|
||||
- "GF_INSTALL_PLUGINS=https://github.com/VictoriaMetrics/victoriametrics-datasource/releases/download/v0.12.1/victoriametrics-metrics-datasource-v0.12.1.zip;victoriametrics-metrics-datasource"
|
||||
- "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=victoriametrics-metrics-datasource"
|
||||
- "GF_INSTALL_PLUGINS=victoriametrics-metrics-datasource"
|
||||
restart: always
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
services:
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:10.4.2
|
||||
image: grafana/grafana:11.5.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- grafanadata:/var/lib/grafana
|
||||
- ./provisioning/datasources/victoriametrics-datasource/single.yml:/etc/grafana/provisioning/datasources/single.yml
|
||||
- ./provisioning/datasources/victoriametrics-metrics-datasource/single.yml:/etc/grafana/provisioning/datasources/single.yml
|
||||
- ./provisioning/dashboards:/etc/grafana/provisioning/dashboards
|
||||
- ./provisioning/plugins/:/var/lib/grafana/plugins
|
||||
- ./../../dashboards/vm/victoriametrics.json:/var/lib/grafana/dashboards/vm.json
|
||||
- ./../../dashboards/vm/vmagent.json:/var/lib/grafana/dashboards/vmagent.json
|
||||
- ./../../dashboards/vm/vmalert.json:/var/lib/grafana/dashboards/vmalert.json
|
||||
environment:
|
||||
- "GF_INSTALL_PLUGINS=https://github.com/VictoriaMetrics/victoriametrics-datasource/releases/download/v0.12.1/victoriametrics-metrics-datasource-v0.12.1.zip;victoriametrics-metrics-datasource"
|
||||
- "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=victoriametrics-metrics-datasource"
|
||||
- GF_INSTALL_PLUGINS=victoriametrics-metrics-datasource
|
||||
networks:
|
||||
- vm_net
|
||||
restart: always
|
||||
|
||||
@@ -22,5 +22,5 @@ to [the latest available releases](https://docs.victoriametrics.com/changelog/).
|
||||
|
||||
## Currently supported LTS release lines
|
||||
|
||||
- v1.102.x - the latest one is [v1.102.11 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.11)
|
||||
- v1.97.x - the latest one is [v1.97.16 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.16)
|
||||
- v1.102.x - the latest one is [v1.102.12 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.12)
|
||||
- v1.97.x - the latest one is [v1.97.17 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.17)
|
||||
|
||||
@@ -42,7 +42,7 @@ Bumping the limits may significantly improve build speed.
|
||||
1. Make sure all the changes are documented in [CHANGELOG.md](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/docs/CHANGELOG.md).
|
||||
Ideally, every change must be documented in the commit with the change. Alternatively, the change must be documented immediately
|
||||
after the commit, which adds the change.
|
||||
1. Run `make vmui-update` and `make vmui-logs-update` commands to re-build static files for `vmui`. See [commit example](https://github.com/VictoriaMetrics/VictoriaMetrics/commit/9dde5b8ee3fdc9d4cd495c8118e04ff4ee32e650).
|
||||
1. Run `make vmui-update` and `make vmui-logs-update` commands to re-build static files for `vmui`. Static assets needs to be rebuilt separately for oss and enterprise branches (changes should not be cherry-picked between these branches). See [commit example](https://github.com/VictoriaMetrics/VictoriaMetrics/commit/9dde5b8ee3fdc9d4cd495c8118e04ff4ee32e650).
|
||||
1. Make sure all the changes are synced between `master`, `cluster`, `enterprise-single-node` and `enterprise-cluster` branches.
|
||||
Changes in these branches must be synced immediately after they are committed in at least a single branch.
|
||||
1. Make sure that the release branches have no security issues.
|
||||
|
||||
@@ -18,8 +18,12 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
|
||||
|
||||
* FEATURE: [`block_stats` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#block_stats-pipe): return the path to the part where every data block is stored. The path to the part is returned in the `part_path` field. This allows investigating the distribution of data blocks among parts.
|
||||
* FEATURE: reduce VictoriaLogs startup time by multiple times when it opens a large datastore with big [retention](https://docs.victoriametrics.com/victorialogs/#retention).
|
||||
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): add the `_msg` field to the list of fields for the group view, allowing users to select multiple fields, including `_msg`, for log display.
|
||||
|
||||
* BUGFIX: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): properly limit [`concurrency` query option](https://docs.victoriametrics.com/victorialogs/logsql/#query-options) for [`stats`](https://docs.victoriametrics.com/victorialogs/logsql/#stats-pipe), [`uniq`](https://docs.victoriametrics.com/victorialogs/logsql/#uniq-pipe) and [`top`](https://docs.victoriametrics.com/victorialogs/logsql/#top-pipe). This prevents from `runtime error: index out of range` panic. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8201).
|
||||
* BUGFIX: [data ingestion](https://docs.victoriametrics.com/victorialogs/data-ingestion/): drop log entries with too long field names and log the dropped log entries with the `ignoring log entry with too long field name` message, so human operators could notice and fix the ingestion of incorrect logs ASAP. Previously too long field names were silently truncated to shorter values. This isn't what most users expect. See [why VictoriaLogs has a limit on the field name length](https://docs.victoriametrics.com/victorialogs/faq/#what-is-the-maximum-supported-field-name-length).
|
||||
* BUGFIX: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): fix transparency for bars in the hits bar chart to improve visibility. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8152).
|
||||
* BUGFIX: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): fix `Group by field` dropdown menu not displaying any options in Group View settings. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8153).
|
||||
|
||||
## [v1.8.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.8.0-victorialogs)
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ See also:
|
||||
### Helm charts
|
||||
|
||||
You can run VictoriaLogs in Kubernetes environment
|
||||
with [these Helm charts](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-logs-single/README.md).
|
||||
with [these Helm charts](https://docs.victoriametrics.com/helm/victorialogs-single/).
|
||||
|
||||
### Building from source code
|
||||
|
||||
@@ -145,5 +145,5 @@ Here are a Docker-compose demos, which start VictoriaLogs and push logs to it vi
|
||||
- [Vector demo](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker/victorialogs/vector)
|
||||
- [Promtail demo](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker/victorialogs/promtail)
|
||||
|
||||
You can use [this Helm chart](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-logs-single/README.md)
|
||||
You can use [this Helm chart](https://docs.victoriametrics.com/helm/victorialogs-single/)
|
||||
as a demo for running Vector in Kubernetes with VictoriaLogs.
|
||||
|
||||
@@ -25,23 +25,6 @@ The VictoriaLogs datasource plugin allows you to query and visualize
|
||||
|
||||
## Installation
|
||||
|
||||
Installing VictoriaLogs datasource
|
||||
[requires](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#allow_loading_unsigned_plugins)
|
||||
the following changes to Grafana's `grafana.ini` config:
|
||||
|
||||
``` ini
|
||||
[plugins]
|
||||
allow_loading_unsigned_plugins = victoriametrics-logs-datasource
|
||||
```
|
||||
|
||||
If using `grafana-operator`, adjust `config` section in your `kind=Grafana` resource as below:
|
||||
|
||||
```
|
||||
config:
|
||||
plugins:
|
||||
allow_loading_unsigned_plugins: "victoriametrics-logs-datasource"
|
||||
```
|
||||
|
||||
For detailed instructions on how to install the plugin in Grafana Cloud or locally,
|
||||
please checkout the [Plugin installation docs](https://grafana.com/docs/grafana/latest/plugins/installation/).
|
||||
|
||||
@@ -80,8 +63,7 @@ Please find the example of provisioning Grafana instance with VictoriaLogs datas
|
||||
grafana:
|
||||
image: grafana/grafana:11.0.0
|
||||
environment:
|
||||
- GF_INSTALL_PLUGINS=https://github.com/VictoriaMetrics/victorialogs-datasource/releases/download/v0.13.1/victoriametrics-logs-datasource-v0.13.1.zip;victoriametrics-logs-datasource
|
||||
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=victoriametrics-logs-datasource
|
||||
- GF_INSTALL_PLUGINS=victoriametrics-logs-datasource
|
||||
ports:
|
||||
- 3000:3000/tcp
|
||||
volumes:
|
||||
@@ -108,15 +90,14 @@ Option 1. Using Grafana provisioning:
|
||||
|
||||
``` yaml
|
||||
env:
|
||||
GF_INSTALL_PLUGINS: "https://github.com/VictoriaMetrics/victorialogs-datasource/releases/download/v0.13.1/victoriametrics-logs-datasource-v0.13.1.zip;victoriametrics-logs-datasource"
|
||||
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: "victoriametrics-logs-datasource"
|
||||
GF_INSTALL_PLUGINS: "victoriametrics-logs-datasource"
|
||||
```
|
||||
|
||||
Option 2. Using Grafana plugins section in `values.yaml`:
|
||||
|
||||
``` yaml
|
||||
plugins:
|
||||
- https://github.com/VictoriaMetrics/victorialogs-datasource/releases/download/v0.13.1/victoriametrics-logs-datasource-v0.13.1.zip;victoriametrics-logs-datasource
|
||||
- victoriametrics-logs-datasource
|
||||
```
|
||||
|
||||
Option 3. Using init container:
|
||||
@@ -170,6 +151,8 @@ apiVersion: grafana.integreatly.org/v1beta1
|
||||
kind: Grafana
|
||||
metadata:
|
||||
name: grafana-vm
|
||||
labels:
|
||||
dashboards: grafana
|
||||
spec:
|
||||
persistentVolumeClaim:
|
||||
spec:
|
||||
@@ -203,14 +186,85 @@ spec:
|
||||
volumeMounts:
|
||||
- name: grafana-data
|
||||
mountPath: /var/lib/grafana
|
||||
config:
|
||||
plugins:
|
||||
allow_loading_unsigned_plugins: victoriametrics-logs-datasource
|
||||
```
|
||||
|
||||
See [Grafana operator reference](https://grafana-operator.github.io/grafana-operator/docs/grafana/) to find more about Grafana operator.
|
||||
This example uses init container to download and install plugin.
|
||||
|
||||
It is also possible to request plugin at `GrafanaDatasource` or `GrafanaDashboard` CRDs.
|
||||
For example:
|
||||
```yaml
|
||||
apiVersion: grafana.integreatly.org/v1beta1
|
||||
kind: GrafanaDatasource
|
||||
metadata:
|
||||
name: vl-datasource
|
||||
spec:
|
||||
datasource:
|
||||
access: proxy
|
||||
type: victoriametrics-logs-datasource
|
||||
name: VL
|
||||
url: http://victoria-logs-single-server.monitoring.svc.cluster.local:9428
|
||||
instanceSelector:
|
||||
matchLabels:
|
||||
dashboards: grafana
|
||||
plugins:
|
||||
- name: victoriametrics-logs-datasource
|
||||
version: "0.14.3"
|
||||
---
|
||||
apiVersion: grafana.integreatly.org/v1beta1
|
||||
kind: GrafanaDashboard
|
||||
metadata:
|
||||
name: vl-dashboard
|
||||
spec:
|
||||
resyncPeriod: 30s
|
||||
plugins:
|
||||
- name: victoriametrics-logs-datasource
|
||||
version: "0.14.3"
|
||||
instanceSelector:
|
||||
matchLabels:
|
||||
dashboards: "grafana"
|
||||
json: |
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [],
|
||||
"preload": false,
|
||||
"refresh": "",
|
||||
"schemaVersion": 40,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Example",
|
||||
"version": 0,
|
||||
"weekStart": ""
|
||||
}
|
||||
```
|
||||
|
||||
### Dev release installation
|
||||
|
||||
1. To download plugin build and move contents into Grafana plugins directory:
|
||||
|
||||
@@ -14,7 +14,7 @@ Please find the changelog for VictoriaMetrics Anomaly Detection below.
|
||||
## v1.19.2
|
||||
Released: 2025-01-27
|
||||
|
||||
- IMPROVEMENT: Added the `complete` option to the `--splitBy` argument in `config_splitter.py` [util](https://docs.victoriametrics.com/anomaly-detection/faq/index.html#splitting-the-config). This allows splitting a parent configuration into the smallest possible sub-configurations, each containing exactly one scheduler, one model, and either one or multiple queries (depending on whether the model is [multivariate](https://docs.victoriametrics.com/anomaly-detection/components/models/#multivariate-models) or not).
|
||||
- IMPROVEMENT: Added the `complete` option to the `--splitBy` argument in `config_splitter.py` [util](https://docs.victoriametrics.com/anomaly-detection/faq/#splitting-the-config). This allows splitting a parent configuration into the smallest possible sub-configurations, each containing exactly one scheduler, one model, and either one or multiple queries (depending on whether the model is [multivariate](https://docs.victoriametrics.com/anomaly-detection/components/models/#multivariate-models) or not).
|
||||
|
||||
- FIX: Resolved an issue where duplicate log messages were generated during sub-config validation of the parent configuration.
|
||||
|
||||
@@ -154,7 +154,7 @@ Released: 2024-10-17
|
||||
- IMPROVEMENT: Accelerated performance of model fitting stages on multicore systems.
|
||||
- IMPROVEMENT: Optimized query handling in multi-[scheduler](https://docs.victoriametrics.com/anomaly-detection/components/scheduler/) setups by filtering [queries](https://docs.victoriametrics.com/anomaly-detection/components/models/#queries) for each scheduler based on model requirements. This reduces unnecessary data fetching from VictoriaMetrics, ensuring only relevant queries are processed by the [VmReader](https://docs.victoriametrics.com/anomaly-detection/components/reader#vm-reader), leading to better performance and efficiency of configs with multiple active schedulers.
|
||||
|
||||
- IMPROVEMENT: Implemented automatic cleanup of files in subdirectories within `/tmp` ([generated by the Stan backend](https://mc-stan.org/cmdstanpy/users-guide/outputs.html) when utilizing [Prophet](https://docs.victoriametrics.com/anomaly-detection/components/models/#prophet) models) after each `fit` operation. This prevents the accumulation of unused data over time in `/tmp`, addressing a potential issue where these files would only be deleted upon termination of the current Python session or service, leading to uncontrolled disk growth.
|
||||
- IMPROVEMENT: Implemented automatic cleanup of files in subdirectories within `/tmp` ([generated by the Stan backend](https://mc-stan.org/cmdstanpy/users-guide/outputs) when utilizing [Prophet](https://docs.victoriametrics.com/anomaly-detection/components/models/#prophet) models) after each `fit` operation. This prevents the accumulation of unused data over time in `/tmp`, addressing a potential issue where these files would only be deleted upon termination of the current Python session or service, leading to uncontrolled disk growth.
|
||||
|
||||
- FIX: Re-enable the `vmanomaly_reader_response_count` (now called `vmanomaly_reader_responses`) self-monitoring [metric](https://docs.victoriametrics.com/anomaly-detection/components/monitoring/#reader-behaviour-metrics) for the [VmReader](https://docs.victoriametrics.com/anomaly-detection/components/reader/#vm-reader), which was unintentionally disabled in previous releases and now updates correctly as intended.
|
||||
|
||||
|
||||
@@ -198,9 +198,9 @@ models:
|
||||
- name: 'dow' # intra-week seasonality, time of the week
|
||||
fourier_order: 2 # keep it 2-4, as dependencies are learned separately for each weekday
|
||||
# inner model args (key-value pairs) accepted by
|
||||
# https://facebook.github.io/prophet/docs/quick_start.html#python-api
|
||||
# https://facebook.github.io/prophet/docs/quick_start#python-api
|
||||
args:
|
||||
interval_width: 0.98 # see https://facebook.github.io/prophet/docs/uncertainty_intervals.html
|
||||
interval_width: 0.98 # see https://facebook.github.io/prophet/docs/uncertainty_intervals
|
||||
|
||||
reader:
|
||||
# https://docs.victoriametrics.com/anomaly-detection/components/reader/#vm-reader
|
||||
@@ -232,4 +232,4 @@ Here are other materials that you might find useful:
|
||||
- [Guide: Anomaly Detection and Alerting Setup](https://docs.victoriametrics.com/anomaly-detection/guides/guide-vmanomaly-vmalert/)
|
||||
- [FAQ](https://docs.victoriametrics.com/anomaly-detection/faq/)
|
||||
- [Changelog](https://docs.victoriametrics.com/anomaly-detection/changelog/)
|
||||
- [Anomaly Detection Blog](https://victoriametrics.com/blog/tags/anomaly-detection/)
|
||||
- [Anomaly Detection Blog](https://victoriametrics.com/tags/anomaly-detection/)
|
||||
|
||||
@@ -43,10 +43,10 @@ Enhance your knowledge with our handbook on Anomaly Detection & Root Cause Analy
|
||||
- [Introduction to Time Series Anomaly Detection](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-1/)
|
||||
- [Types of Anomalies in Time Series Data](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-2/)
|
||||
- [Techniques and Models for Anomaly Detection](https://victoriametrics.com/blog/victoriametrics-anomaly-detection-handbook-chapter-3/)
|
||||
* Follow the [`#anomaly-detection`](https://victoriametrics.com/blog/tags/anomaly-detection/) tag in our blog
|
||||
* Follow the [`#anomaly-detection`](https://victoriametrics.com/tags/anomaly-detection/) tag in our blog
|
||||
|
||||
## Product Updates
|
||||
Stay up-to-date with the latest improvements and features in VictoriaMetrics Anomaly Detection, and the rest of our products on our [blog](https://victoriametrics.com/blog/tags/product-updates/).
|
||||
Stay up-to-date with the latest improvements and features in VictoriaMetrics Anomaly Detection, and the rest of our products on our [blog](https://victoriametrics.com/tags/product-updates/).
|
||||
|
||||
## Frequently Asked Questions (FAQ)
|
||||
Got questions about VictoriaMetrics Anomaly Detection? Chances are, we've got the answers ready for you.
|
||||
|
||||
@@ -389,7 +389,7 @@ Every other model that isn't [online](#online-models). Offline models are comple
|
||||
VictoriaMetrics Anomaly Detection models support 2 groups of parameters:
|
||||
|
||||
- **`vmanomaly`-specific** arguments - please refer to *Parameters specific for vmanomaly* and *Default model parameters* subsections for each of the models below.
|
||||
- Arguments to **inner model** (say, [Facebook's Prophet](https://facebook.github.io/prophet/docs/quick_start.html#python-api)), passed in a `args` argument as key-value pairs, that will be directly given to the model during initialization to allow granular control. Optional.
|
||||
- Arguments to **inner model** (say, [Facebook's Prophet](https://facebook.github.io/prophet/docs/quick_start#python-api)), passed in a `args` argument as key-value pairs, that will be directly given to the model during initialization to allow granular control. Optional.
|
||||
|
||||
> **Note**: For users who may not be familiar with Python data types such as `list[dict]`, a [dictionary](https://www.w3schools.com/python/python_dictionaries.asp) in Python is a data structure that stores data values in key-value pairs. This structure allows for efficient data retrieval and management.
|
||||
|
||||
@@ -418,7 +418,7 @@ Tuning hyperparameters of a model can be tricky and often requires in-depth know
|
||||
* `tuned_class_name` (string) - Built-in model class to tune, i.e. `model.zscore.ZscoreModel` (or `zscore`with class alias support{{% available_from "v1.13.0" anomaly %}}).
|
||||
* `optimization_params` (dict) - Optimization parameters for unsupervised model tuning. Control % of found anomalies, as well as a tradeoff between time spent and the accuracy. The more `timeout` and `n_trials` are, the better model configuration can be found for `tuned_class_name`, but the longer it takes and vice versa. Set `n_jobs` to `-1` to use all the CPUs available, it makes sense if only you have a big dataset to train on during `fit` calls, otherwise overhead isn't worth it.
|
||||
- `anomaly_percentage` (float) - Expected percentage of anomalies that can be seen in training data, from (0, 0.5) interval.
|
||||
- `optimized_business_params` (list[string]) - Starting from [v1.15.0](https://docs.victoriametrics.com/anomaly-detection/v1150) this argument allows particular business-specific parameters such as [`detection_direction`](https://docs.victoriametrics.com/anomaly-detection/components/models/#detection-direction) or [`min_dev_from_expected`](https://docs.victoriametrics.com/anomaly-detection/components/models/#minimal-deviation-from-expected) to remain **unchanged during optimizations, retaining their default values**. I.e. setting `optimized_business_params` to `['detection_direction']` will allow to optimize only `detection_direction` business-specific arg, while `min_dev_from_expected` will retain its default value (0.0). By default and if not set, will be equal to `[]` (empty list), meaning no business params will be optimized. **A recommended option is to leave it empty** for more stable results and increased convergence (less iterations needed for a good result).
|
||||
- `optimized_business_params` (list[string]) - Starting from [v1.15.0](https://docs.victoriametrics.com/anomaly-detection/changelog/#v1150) this argument allows particular business-specific parameters such as [`detection_direction`](https://docs.victoriametrics.com/anomaly-detection/components/models/#detection-direction) or [`min_dev_from_expected`](https://docs.victoriametrics.com/anomaly-detection/components/models/#minimal-deviation-from-expected) to remain **unchanged during optimizations, retaining their default values**. I.e. setting `optimized_business_params` to `['detection_direction']` will allow to optimize only `detection_direction` business-specific arg, while `min_dev_from_expected` will retain its default value (0.0). By default and if not set, will be equal to `[]` (empty list), meaning no business params will be optimized. **A recommended option is to leave it empty** for more stable results and increased convergence (less iterations needed for a good result).
|
||||
- `seed` (int) - Random seed for reproducibility and deterministic nature of underlying optimizations.
|
||||
- `n_splits` (int) - How many folds to create for hyperparameter tuning out of your data. The higher, the longer it takes but the better the results can be. Defaults to 3.
|
||||
- `n_trials` (int) - How many trials to sample from hyperparameter search space. The higher, the longer it takes but the better the results can be. Defaults to 128.
|
||||
@@ -451,7 +451,7 @@ models:
|
||||
|
||||
|
||||
### [Prophet](https://facebook.github.io/prophet/)
|
||||
`vmanomaly` uses the Facebook Prophet implementation for time series forecasting, with detailed usage provided in the [Prophet library documentation](https://facebook.github.io/prophet/docs/quick_start.html#python-api). All original Prophet parameters are supported and can be directly passed to the model via `args` argument.
|
||||
`vmanomaly` uses the Facebook Prophet implementation for time series forecasting, with detailed usage provided in the [Prophet library documentation](https://facebook.github.io/prophet/docs/quick_start#python-api). All original Prophet parameters are supported and can be directly passed to the model via `args` argument.
|
||||
|
||||
|
||||
> **Note**: `ProphetModel` is a [univariate](#univariate-models), [non-rolling](#non-rolling-models), [offline](#offline-models) model.
|
||||
@@ -462,7 +462,7 @@ models:
|
||||
*Parameters specific for vmanomaly*:
|
||||
|
||||
- `class` (string) - model class name `"model.prophet.ProphetModel"` (or `prophet` with class alias support{{% available_from "v1.13.0" anomaly %}})
|
||||
- `seasonalities` (list[dict], optional): Additional seasonal components to include in Prophet. See Prophet’s [`add_seasonality()`](https://facebook.github.io/prophet/docs/seasonality,_holiday_effects,_and_regressors.html#modeling-holidays-and-special-events:~:text=modeling%20the%20cycle-,Specifying,-Custom%20Seasonalities) documentation for details.
|
||||
- `seasonalities` (list[dict], optional): Additional seasonal components to include in Prophet. See Prophet’s [`add_seasonality()`](https://facebook.github.io/prophet/docs/seasonality,_holiday_effects,_and_regressors#modeling-holidays-and-special-events:~:text=modeling%20the%20cycle-,Specifying,-Custom%20Seasonalities) documentation for details.
|
||||
- `scale`{{% available_from "v1.18.0" anomaly %}} (float): Is used to adjust the margin between `yhat` and [`yhat_lower`, `yhat_upper`]. New margin = `|yhat_* - yhat_lower| * scale`. Defaults to 1 (no scaling is applied).
|
||||
- `tz_aware`{{% available_from "v1.18.0" anomaly %}} (bool): Enables handling of timezone-aware timestamps. Default is `False`. Should be used with `tz_seasonalities` and `tz_use_cyclical_encoding` parameters.
|
||||
- `tz_seasonalities`{{% available_from "v1.18.0" anomaly %}} (list[dict]): Specifies timezone-aware seasonal components. Requires `tz_aware=True`. Supported options include `minute`, `hod` (hour of day), `dow` (day of week), and `month` (month of year). Starting with [v1.18.2](https://docs.victoriametrics.com/anomaly-detection/changelog/#v1182), users can configure additional parameters for each seasonality, such as `fourier_order`, `prior_scale`, and `mode`. For more details, please refer to the **Timezone-unaware** configuration example below.
|
||||
@@ -495,9 +495,9 @@ models:
|
||||
fourier_order: 30
|
||||
prior_scale: 20
|
||||
# inner model args (key-value pairs) accepted by
|
||||
# https://facebook.github.io/prophet/docs/quick_start.html#python-api
|
||||
# https://facebook.github.io/prophet/docs/quick_start#python-api
|
||||
args:
|
||||
interval_width: 0.98 # see https://facebook.github.io/prophet/docs/uncertainty_intervals.html
|
||||
interval_width: 0.98 # see https://facebook.github.io/prophet/docs/uncertainty_intervals
|
||||
country_holidays: 'US'
|
||||
```
|
||||
|
||||
@@ -517,9 +517,9 @@ models:
|
||||
- name: 'dow' # intra-week seasonality, time of the week
|
||||
fourier_order: 2 # keep it 2-4, as dependencies are learned separately for each weekday
|
||||
# inner model args (key-value pairs) accepted by
|
||||
# https://facebook.github.io/prophet/docs/quick_start.html#python-api
|
||||
# https://facebook.github.io/prophet/docs/quick_start#python-api
|
||||
args:
|
||||
interval_width: 0.98 # see https://facebook.github.io/prophet/docs/uncertainty_intervals.html
|
||||
interval_width: 0.98 # see https://facebook.github.io/prophet/docs/uncertainty_intervals
|
||||
country_holidays: 'US'
|
||||
```
|
||||
|
||||
@@ -578,7 +578,7 @@ Resulting metrics of the model are described [here](#vmanomaly-output).
|
||||
|
||||
> **Note**: `HoltWinters` is a [univariate](#univariate-models), [non-rolling](#non-rolling-models), [offline](#offline-models) model.
|
||||
|
||||
Here we use Holt-Winters Exponential Smoothing implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html). All parameters from this library can be passed to the model.
|
||||
Here we use Holt-Winters Exponential Smoothing implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing). All parameters from this library can be passed to the model.
|
||||
|
||||
*Parameters specific for vmanomaly*:
|
||||
|
||||
@@ -596,11 +596,11 @@ Used to compute "seasonal_periods" param for the model (e.g. '1D' or '1W').
|
||||
|
||||
*Default model parameters*:
|
||||
|
||||
* If [parameter](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters) `seasonal` is not specified, default value will be `add`.
|
||||
* If [parameter](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters) `seasonal` is not specified, default value will be `add`.
|
||||
|
||||
* If [parameter](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters) `initialization_method` is not specified, default value will be `estimated`.
|
||||
* If [parameter](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters) `initialization_method` is not specified, default value will be `estimated`.
|
||||
|
||||
* `args` (dict, optional) - Inner model args (key-value pairs). See accepted params in [model documentation](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing.html#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters). Defaults to empty (not provided). Example: {"seasonal": "add", "initialization_method": "estimated"}
|
||||
* `args` (dict, optional) - Inner model args (key-value pairs). See accepted params in [model documentation](https://www.statsmodels.org/dev/generated/statsmodels.tsa.holtwinters.ExponentialSmoothing#statsmodels.tsa.holtwinters.ExponentialSmoothing-parameters). Defaults to empty (not provided). Example: {"seasonal": "add", "initialization_method": "estimated"}
|
||||
|
||||
*Config Example*
|
||||
|
||||
@@ -746,7 +746,7 @@ Resulting metrics of the model are described [here](#vmanomaly-output).
|
||||
|
||||
> **Note**: `StdModel` is a [univariate](#univariate-models), [rolling](#rolling-models), [offline](#offline-models) model.
|
||||
|
||||
Here we use Seasonal Decompose implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.seasonal.seasonal_decompose.html). Parameters from this library can be passed to the model. Some parameters are specifically predefined in `vmanomaly` and can't be changed by user(`model`='additive', `two_sided`=False).
|
||||
Here we use Seasonal Decompose implementation from `statsmodels` [library](https://www.statsmodels.org/dev/generated/statsmodels.tsa.seasonal.seasonal_decompose). Parameters from this library can be passed to the model. Some parameters are specifically predefined in `vmanomaly` and can't be changed by user(`model`='additive', `two_sided`=False).
|
||||
|
||||
*Parameters specific for vmanomaly*:
|
||||
|
||||
@@ -784,7 +784,7 @@ Detects anomalies using binary trees. The algorithm has a linear time complexity
|
||||
|
||||
**Important**: Be aware of [the curse of dimensionality](https://en.wikipedia.org/wiki/Curse_of_dimensionality). Don't use single multivariate model if you expect your queries to return many time series of less datapoints that the number of metrics. In such case it is hard for a model to learn meaningful dependencies from too sparse data hypercube.
|
||||
|
||||
Here we use Isolation Forest implementation from `scikit-learn` [library](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html). All parameters from this library can be passed to the model.
|
||||
Here we use Isolation Forest implementation from `scikit-learn` [library](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest). All parameters from this library can be passed to the model.
|
||||
|
||||
*Parameters specific for vmanomaly*:
|
||||
|
||||
@@ -801,7 +801,7 @@ Here we use Isolation Forest implementation from `scikit-learn` [library](https:
|
||||
- "dow" - day of week (1-7)
|
||||
- "month" - month of year (1-12)
|
||||
|
||||
* `args` (dict, optional) - Inner model args (key-value pairs). See accepted params in [model documentation](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html). Defaults to empty (not provided). Example: {"random_state": 42, "n_estimators": 100}
|
||||
* `args` (dict, optional) - Inner model args (key-value pairs). See accepted params in [model documentation](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest). Defaults to empty (not provided). Example: {"random_state": 42, "n_estimators": 100}
|
||||
|
||||
*Config Example*
|
||||
|
||||
|
||||
@@ -851,11 +851,11 @@ When there are insufficient valid data points (at least 1 for [online models](ht
|
||||
[Scheduler {{scheduler_alias}}] Skipping run for stage 'fit' for model '{{model_alias}}' (query_key: {{query_key}}): Not enough valid data to fit: {{valid_values_cnt}}
|
||||
```
|
||||
|
||||
When all the received timestamps during an `infer` call have already been processed, meaning the [`anomaly_score`](https://docs.victoriametrics.com/anomaly-detection/faq/index.html#what-is-anomaly-score) has already been produced for those points
|
||||
When all the received timestamps during an `infer` call have already been processed, meaning the [`anomaly_score`](https://docs.victoriametrics.com/anomaly-detection/faq/#what-is-anomaly-score) has already been produced for those points
|
||||
```text
|
||||
[Scheduler {{scheduler_alias}}] Skipping run for stage 'infer' for model '{{model_alias}}' (query_key: {{query_key}}): No unseen data to infer on.
|
||||
```
|
||||
When the model fails to produce any valid or finite outputs (such as [`anomaly_score`](https://docs.victoriametrics.com/anomaly-detection/faq/index.html#what-is-anomaly-score))
|
||||
When the model fails to produce any valid or finite outputs (such as [`anomaly_score`](https://docs.victoriametrics.com/anomaly-detection/faq/#what-is-anomaly-score))
|
||||
```text
|
||||
[Scheduler {{scheduler_alias}}] Skipping run for stage 'infer' for model '{{model_alias}}' (query_key: {{query_key}}): No (valid) datapoints produced.
|
||||
```
|
||||
@@ -917,7 +917,7 @@ For [rolling models](https://docs.victoriametrics.com/anomaly-detection/componen
|
||||
|
||||
### Writer logs
|
||||
|
||||
The `writer` component logs events during the process of sending produced data (like `anomaly_score` [metrics](https://docs.victoriametrics.com/anomaly-detection/faq/index.html#what-is-anomaly-score)) to VictoriaMetrics. This includes data preparation, serialization, and network requests to VictoriaMetrics endpoints. The logs can help identify issues in data transmission, such as connection errors, invalid data points, and track the performance of write requests.
|
||||
The `writer` component logs events during the process of sending produced data (like `anomaly_score` [metrics](https://docs.victoriametrics.com/anomaly-detection/faq/#what-is-anomaly-score)) to VictoriaMetrics. This includes data preparation, serialization, and network requests to VictoriaMetrics endpoints. The logs can help identify issues in data transmission, such as connection errors, invalid data points, and track the performance of write requests.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ There is change{{% available_from "v1.13.0" anomaly %}} of [`queries`](https://d
|
||||
|
||||
> **Note**: if not set explicitly (or if older config style prior to [v1.13.0](https://docs.victoriametrics.com/anomaly-detection/changelog/#v1130)) is used, then it is set to reader-level `data_range` arg{{% available_from "v1.18.1" anomaly %}}
|
||||
|
||||
- `max_points_per_query` (int): Optional arg{{% available_from "v1.17.0" anomaly %}} overrides how `search.maxPointsPerTimeseries` flag{{% available_from "v1.14.1" anomaly %}} impacts `vmanomaly` on splitting long `fit_window` [queries](https://docs.victoriametrics.com/anomaly-detection/components/reader/?highlight=queries#vm-reader) into smaller sub-intervals. This helps users avoid hitting the `search.maxQueryDuration` limit for individual queries by distributing initial query across multiple subquery requests with minimal overhead. Set less than `search.maxPointsPerTimeseries` if hitting `maxQueryDuration` limits. If set on a query-level, it overrides the global `max_points_per_query` (reader-level).
|
||||
- `max_points_per_query`{{% available_from "v1.17.0" anomaly %}} (int): Optional arg, overrides how `search.maxPointsPerTimeseries` flag{{% available_from "v1.14.1" anomaly %}} impacts `vmanomaly` on splitting long `fit_window` [queries](https://docs.victoriametrics.com/anomaly-detection/components/reader/?highlight=queries#vm-reader) into smaller sub-intervals. This helps users avoid hitting the `search.maxQueryDuration` limit for individual queries by distributing initial query across multiple subquery requests with minimal overhead. Set less than `search.maxPointsPerTimeseries` if hitting `maxQueryDuration` limits. If set on a query-level, it overrides the global `max_points_per_query` (reader-level).
|
||||
|
||||
- `tz`{{% available_from "v1.18.0" anomaly %}} (string): this optional argument enables timezone specification per query, overriding the reader’s default `tz`. This setting helps to account for local timezone shifts, such as [DST](https://en.wikipedia.org/wiki/Daylight_saving_time), in models that are sensitive to seasonal variations (e.g., [`ProphetModel`](https://docs.victoriametrics.com/anomaly-detection/components/models/#prophet) or [`OnlineQuantileModel`](https://docs.victoriametrics.com/anomaly-detection/components/models/#online-seasonal-quantile)).
|
||||
|
||||
@@ -76,9 +76,9 @@ There is change{{% available_from "v1.13.0" anomaly %}} of [`queries`](https://d
|
||||
- if *set, overrides* reader-level `tenant_id`
|
||||
- *raises config validation error*, if *reader-level is not set* and *query-level is found* (mixing of VictoriaMetrics [single-node](https://docs.victoriametrics.com/single-server-victoriametrics/) and [cluster](https://docs.victoriametrics.com/cluster-victoriametrics/) is prohibited in a single config)
|
||||
- *raises config validation warning*, if `writer.tenant_id` is not explicitly set to `multitenant` when reader uses tenants, meaning [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/) will be used for data querying.
|
||||
- also *raises config validation error* if a set of `reader.queries` for [multivariate models](https://docs.victoriametrics.com/anomaly-detection/components/models/index.html#multivariate-models) has *different* tenant_ids (meaning tenant data is mixed, and special labels like `vm_project_id`, `vm_account_id` will have [ambiguous values](https://docs.victoriametrics.com/cluster-victoriametrics/#multitenancy-via-labels))
|
||||
- also *raises config validation error* if a set of `reader.queries` for [multivariate models](https://docs.victoriametrics.com/anomaly-detection/components/models/#multivariate-models) has *different* tenant_ids (meaning tenant data is mixed, and special labels like `vm_project_id`, `vm_account_id` will have [ambiguous values](https://docs.victoriametrics.com/cluster-victoriametrics/#multitenancy-via-labels))
|
||||
|
||||
> **Note:** The recommended approach for using per-query `tenant_id`s is to set both `reader.tenant_id` and `writer.tenant_id` to `multitenant`. See [this section](https://docs.victoriametrics.com/anomaly-detection/components/writer/index.html#multitenancy-support) for more details. Configurations where `reader.tenant_id` equals `writer.tenant_id` and is not `multitenant` are also considered safe, provided there is a single, DISTINCT `tenant_id` defined in the reader (either at the reader level or the query level, if set).
|
||||
> **Note:** The recommended approach for using per-query `tenant_id`s is to set both `reader.tenant_id` and `writer.tenant_id` to `multitenant`. See [this section](https://docs.victoriametrics.com/anomaly-detection/components/writer/#multitenancy-support) for more details. Configurations where `reader.tenant_id` equals `writer.tenant_id` and is not `multitenant` are also considered safe, provided there is a single, DISTINCT `tenant_id` defined in the reader (either at the reader level or the query level, if set).
|
||||
|
||||
### Per-query config example
|
||||
```yaml
|
||||
@@ -348,7 +348,7 @@ If True, then query will be performed from the last seen timestamp for a given s
|
||||
`1ms`
|
||||
</td>
|
||||
<td>
|
||||
It allows overriding the default `-search.latencyOffset`{{% available_from "v1.15.1" anomaly %}} [flag of VictoriaMetrics](https://docs.victoriametrics.com/?highlight=search.latencyOffset#list-of-command-line-flags) (30s). The default value is set to 1ms, which should help in cases where `sampling_frequency` is low (10-60s) and `sampling_frequency` equals `infer_every` in the [PeriodicScheduler](https://docs.victoriametrics.com/anomaly-detection/components/scheduler/?highlight=infer_every#periodic-scheduler). This prevents users from receiving `service - WARNING - [Scheduler [scheduler_alias]] No data available for inference.` warnings in logs and allows for consecutive `infer` calls without gaps. To restore the old behavior, set it equal to your `-search.latencyOffset` [flag value]((https://docs.victoriametrics.com/?highlight=search.latencyOffset#list-of-command-line-flags)).
|
||||
It allows overriding the default `-search.latencyOffset`{{% available_from "v1.15.1" anomaly %}} [flag of VictoriaMetrics](https://docs.victoriametrics.com/?highlight=search.latencyOffset#list-of-command-line-flags) (30s). The default value is set to 1ms, which should help in cases where `sampling_frequency` is low (10-60s) and `sampling_frequency` equals `infer_every` in the [PeriodicScheduler](https://docs.victoriametrics.com/anomaly-detection/components/scheduler/?highlight=infer_every#periodic-scheduler). This prevents users from receiving `service - WARNING - [Scheduler [scheduler_alias]] No data available for inference.` warnings in logs and allows for consecutive `infer` calls without gaps. To restore the old behavior, set it equal to your `-search.latencyOffset` [flag value](https://docs.victoriametrics.com/?highlight=search.latencyOffset#list-of-command-line-flags).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -121,7 +121,7 @@ Detailed parameters in each section:
|
||||
|
||||
* `models`
|
||||
* `class` - Specifies the model to be used. Options include custom models ([guide here](https://docs.victoriametrics.com/anomaly-detection/components/models/#custom-model-guide)) or a selection from [built-in models](https://docs.victoriametrics.com/anomaly-detection/components/models/#built-in-models), such as the [Facebook Prophet](https://docs.victoriametrics.com/anomaly-detection/components/models/#prophet) (`model.prophet.ProphetModel`).
|
||||
* `args` - Model-specific parameters, formatted as a YAML dictionary in the `key: value` structure. Parameters available in [FB Prophet](https://facebook.github.io/prophet/docs/quick_start.html) can be used as an example.
|
||||
* `args` - Model-specific parameters, formatted as a YAML dictionary in the `key: value` structure. Parameters available in [FB Prophet](https://facebook.github.io/prophet/docs/quick_start) can be used as an example.
|
||||
|
||||
* `reader`
|
||||
* `datasource_url` - The URL for the data source, typically an HTTP endpoint serving `/api/v1/query_range`.
|
||||
|
||||
@@ -19,6 +19,17 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
|
||||
## tip
|
||||
|
||||
* FEATURE: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and [vmstorage](https://docs.victoriametrics.com/cluster-victoriametrics/): improve startup times when opening a storage with the [retention](https://docs.victoriametrics.com/#retention) exceeding a few months.
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add the ability to switch the heatmap to a line chart. Now, vmui would suggest to switch to line graph display if heatmap can't be properly rendered. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8057).
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): add `-httpInternalListenAddr` cmd-line flag to serve internal HTTP routes `/metrics`, `/flags`, etc. It allows properly route requests to backends with the same service routes as vmauth. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6468) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7345) for details.
|
||||
* FEATURE: expose `/-/healthy` and `/-/ready` endpoints as Prometheus does on vmselect endpoints, thus achieving full Prometheus compatibility for external dependencies.
|
||||
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent/): properly perform graceful shutdown for kafka client.
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent/): properly add message metadata headers for kafka remoteWrite target.
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): improve clipboard error handling in tables and code snippets by showing detailed messages with possible reasons. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7778).
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui) for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html) components: properly display enterprise features when the enterprise version is used.
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): fix discrepancies when using `or` binary operator. See [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7759) and [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7640) issues for details.
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): properly update number of unique series for [cardinality limiter](https://docs.victoriametrics.com/#cardinality-limiter) on ingestion. Previously, limit could undercount the real number of the ingested unique series.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): do not unregister group metrics if the group is still in use. Previously, this could lead to group metrics being absent even though rules group is still running. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8229) for details.
|
||||
|
||||
## [v1.102.12](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.12)
|
||||
|
||||
@@ -37,7 +48,7 @@ Released at 2025-01-28
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/), `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/) and [vmagent](https://docs.victoriametrics.com/vmagent/): log metric names for signals with unsupported delta temporality on ingestion via [OpenTelemetry protocol for metrics](https://docs.victoriametrics.com/#sending-data-via-opentelemetry). Thanks to @chenlujjj for [the pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8018).
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): respect staleness detection in increase, increase_pure and delta functions when time series has gaps and `-search.maxStalenessInterval` is set. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8072) for details.
|
||||
@@ -49,8 +60,9 @@ Released at 2025-01-24
|
||||
* SECURITY: upgrade Go builder from Go1.23.4 to Go1.23.5. See the list of issues addressed in [Go1.23.5](https://github.com/golang/go/issues?q=milestone%3AGo1.23.5+label%3ACherryPickApproved).
|
||||
|
||||
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/metricsql/): allow executing queries with `$__interval` and `$__rate_interval` - these placeholders are automatically replaced with `1i` (e.g. `step` arg value at [`/api/v1/query_range`](https://docs.victoriametrics.com/keyconcepts/#range-query)) during query execution. This simplifies copying queries from Grafana dashboards.
|
||||
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/metricsql/): allow specifying metric names in quotes inside `{}` braces: `{"metric_name", job="foo"}` is equal to `metric_name{job="foo"}`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7703) for details.
|
||||
* FEATURE: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/) and `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): add command-line flag `-search.maxDeleteDuration(default 5m)` to limit the duration of the `/api/v1/admin/tsdb/delete_series` call. Previously, the call is limited by `-search.maxQueryDuration`.
|
||||
* FEATURE: [dashboards](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards): all dashboards that use [VictoriaMetrics Grafana datasource](https://github.com/VictoriaMetrics/victoriametrics-datasource) were updated to use a [new datasource ID](https://github.com/VictoriaMetrics/victoriametrics-datasource/releases/tag/v0.12.0).
|
||||
* FEATURE: [dashboards](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards): all dashboards that use [VictoriaMetrics Grafana datasource](https://github.com/VictoriaMetrics/victoriametrics-datasource) were updated to use a [new datasource ID](https://github.com/VictoriaMetrics/victoriametrics-datasource/releases/tag/v0.12.0).
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): reflect column settings for the table view in URL, so the table view can be shared via link. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7662).
|
||||
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): fix possible runtime panic during requests processing under heavy load. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8051) for details.
|
||||
@@ -60,11 +72,14 @@ Released at 2025-01-24
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): respect staleness detection in increase, increase_pure and delta functions when time series has gaps and `-search.maxStalenessInterval` is set. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8072) for details.
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/), `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/) and [vmagent](https://docs.victoriametrics.com/vmagent/): allow ingesting histograms with missing `_sum` metric via [OpenTelemetry ingestion protocol](https://docs.victoriametrics.com/#sending-data-via-opentelemetry) in the same way as Prometheus does.
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix an issue where pressing the "Enter" key in the query editor did not execute the query. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8058).
|
||||
* BUGFIX: [export API](https://docs.victoriametrics.com/#how-to-export-time-series): cancel export process on client connection close. Previously client connection close was ignored and VictoriaMetrics started to hog CPU by exporting metrics to nowhere until it export all of them.
|
||||
|
||||
## [v1.102.11](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.11)
|
||||
|
||||
Released at 2025-01-24
|
||||
|
||||
It is recommended upgrading to [v1.102.12](https://docs.victoriametrics.com/changelog/#v110212) because [v1.102.11](https://docs.victoriametrics.com/changelog/#v110211) contains a bug with staleness detection.
|
||||
|
||||
**v1.102.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.102.x line will be supported for at least 12 months since [v1.102.0](https://docs.victoriametrics.com/changelog/#v11020) release**
|
||||
@@ -81,9 +96,11 @@ The v1.102.x line will be supported for at least 12 months since [v1.102.0](http
|
||||
|
||||
Released at 2025-01-24
|
||||
|
||||
It is recommended upgrading to [v1.97.17](https://docs.victoriametrics.com/changelog/#v19717) because [v1.97.16](https://docs.victoriametrics.com/changelog/#v19716) contains a bug with staleness detection.
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: all VictoriaMetrics [enterprise](https://docs.victoriametrics.com/enterprise/) components: remove unnecessary delay before failing if all online verification attempts have failed. This should reduce the time required for the component to proceed if all online verification attempts have failed.
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): don't take into account the last raw sample before the lookbehind window is sample exceeds the staleness interval. This affects correctness of increase, increase_pure, delta functions when preforming calculations on time series with gaps. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8002) for details.
|
||||
@@ -123,7 +140,7 @@ Released at 2025-01-14
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): properly set `host` field at debug information formatted with `dump_request_on_errors: true` setting.
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): properly handle discovery for ipv6 addresses. Thanks to @badie for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7955).
|
||||
* BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl/): fix support for migrating influx series without any tag. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7921). Thanks to @bitbidu for reporting.
|
||||
* BUGFIX: [vminsert](https://docs.victoriametrics.com/vminsert/): storage nodes defined in `-storageNode` are now sorted, ensuring that varying node orders across different vminsert instances do not result in inconsistent replication.
|
||||
* BUGFIX: `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): storage nodes defined in `-storageNode` are now sorted, ensuring that varying node orders across different vminsert instances do not result in inconsistent replication.
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/) and `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): properly ingest `influx` line protocol metrics with empty tags. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7933) for details.
|
||||
* BUGFIX: [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): allow to override the default unique time series limit in vmstorage with command-line flags like `-search.maxUniqueTimeseries`, `-search.maxLabelsAPISeries`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7852).
|
||||
* BUGFIX: [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): properly set tenancy information when evaluating numbers in a query. Previously, the tenancy information could lead to mismatch between query result and a number. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7987) for the details.
|
||||
@@ -140,8 +157,7 @@ Released at 2025-01-14
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix cursor reset in query input field. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7288).
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): properly handle discovery for ipv6 addresses. Thanks to @badie for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7955).
|
||||
* BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl/): fix support for migrating influx series without any tag. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7921). Thanks to @bitbidu for reporting.
|
||||
* BUGFIX: [vminsert](https://docs.victoriametrics.com/vminsert/): storage nodes defined in `-storageNode` are now sorted, ensuring that varying node orders across different vminsert instances do not result in inconsistent replication.
|
||||
|
||||
* BUGFIX: `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): storage nodes defined in `-storageNode` are now sorted, ensuring that varying node orders across different vminsert instances do not result in inconsistent replication.
|
||||
|
||||
## [v1.97.15](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.15)
|
||||
|
||||
@@ -151,7 +167,7 @@ Released at 2025-01-14
|
||||
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/), `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): make instant query results consistent. VictoriaMetrics detects and adjusts scrape interval and while this is very useful for range queries (i.e. this eliminates gaps on the graph), it may cause instant queries to return a non-empty result when no result is expected. The fix is to disable scrape interval detection and always use the step as the scrape interval in instant queries. This will guarantee that the samples are searched within the (time-step, time] interval. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5796) for details.
|
||||
* BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl/): fix support for migrating influx series without any tag. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7921). Thanks to @bitbidu for reporting.
|
||||
* BUGFIX: [vminsert](https://docs.victoriametrics.com/vminsert/): storage nodes defined in `-storageNode` are now sorted, ensuring that varying node orders across different vminsert instances do not result in inconsistent replication.
|
||||
* BUGFIX: `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): storage nodes defined in `-storageNode` are now sorted, ensuring that varying node orders across different vminsert instances do not result in inconsistent replication.
|
||||
|
||||
## [v1.108.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.108.1)
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@ Released at 2024-12-13
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* SECURITY: upgrade base docker image (Alpine) from 3.20.3 to 3.21.0. See [alpine 3.21.0 release notes](https://alpinelinux.org/posts/Alpine-3.21.0-released.html).
|
||||
* SECURITY: upgrade Go builder from Go1.23.3 to Go1.23.4. See the list of issues addressed in [Go1.23.4](https://github.com/golang/go/issues?q=milestone%3AGo1.23.4+label%3ACherryPickApproved).
|
||||
@@ -748,7 +748,7 @@ Released at 2024-11-29
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent): return `200 OK` HTTP status code when importing data via [Pushgateway protocol](https://docs.victoriametrics.com/#how-to-import-data-in-prometheus-exposition-format) using [multitenant URL format](https://docs.victoriametrics.com/cluster-victoriametrics/#url-format). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3636) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7571).
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent): properly set `TCP` connection timeout for `Kubernetes API server` connection for metric scrapping with `kubernetes_sd_configs`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7127).
|
||||
@@ -762,7 +762,7 @@ Released at 2024-11-15
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl/): drop rows that do not belong to the current series during import. The dropped rows should belong to another series whose tags are a superset of the current series. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7301) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7330). Thanks to @dpedu for reporting and cooperating with the test.
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/), `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): keep the order of resulting time series when `limit_offset` is applied. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7068).
|
||||
@@ -776,7 +776,7 @@ Released at 2024-11-04
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert): properly set `group_name` and `file` fields for recording rules in `/api/v1/rules`.
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): prevent panic when ingesting samples which are outside of configured [retention filters](https://docs.victoriametrics.com/#retention-filters). This could happen when backfilling data with retention filters which exclude samples from the backfill range.
|
||||
@@ -787,7 +787,7 @@ Released at 2024-10-21
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix error messages rendering from overflowing the screen with long messages. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7207).
|
||||
* BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl/): properly add metrics tags for `opentsdb` migration source. Previously it could have empty values. See [this PR](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7161).
|
||||
@@ -800,7 +800,7 @@ Released at 2024-10-02
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/metricsql/): consistently return the first non-`NaN` value from [`range_first`](https://docs.victoriametrics.com/metricsql/#range_first) function across all the returned data points. Previously `NaN` data points weren't replaced with the first non-`NaN` value.
|
||||
|
||||
@@ -830,7 +830,7 @@ Released at 2024-08-28
|
||||
|
||||
**v1.97.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes for [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html).
|
||||
All these fixes are also included in [the latest community release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/CHANGELOG.html#v1970) release**
|
||||
The v1.97.x line will be supported for at least 12 months since [v1.97.0](https://docs.victoriametrics.com/changelog/#v1970) release**
|
||||
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent): fixes `proxy_url` authorization for scrape targets. Previously proxy authorization configuration was ignored for `https` targets. See [this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6771) issue for details.
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent/) fix service discovery of Azure Virtual Machines for response contains `nextLink`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6784).
|
||||
|
||||
@@ -258,12 +258,13 @@ consider [backfilling tips](https://docs.victoriametrics.com/single-server-victo
|
||||
* _VictoriaMetrics may return non-existing data points if `step` param is lower than the actual data resolution. See
|
||||
more about this [here](https://docs.victoriametrics.com/keyconcepts/#range-query)._
|
||||
* How do I get the `real` last data point, not `ephemeral`?
|
||||
* _[last_over_time](https://docs.victoriametrics.com/metricsql/#last_over_time) function can be used for
|
||||
limiting the lookbehind window for calculated data. For example, `last_over_time(metric[10s])` would return
|
||||
calculated samples only if the real samples are located closer than 10 seconds to the calculated timestamps
|
||||
according to
|
||||
`start`, `end` and `step` query args passed
|
||||
* _[last_over_time](https://docs.victoriametrics.com/metricsql/#last_over_time) function returns last value on
|
||||
the given look-behind window. For example, `last_over_time(metric[10s])` would return
|
||||
sample values only if the real samples are located closer than 10 seconds to the calculated timestamps
|
||||
according to `start`, `end` and `step` query args passed
|
||||
to [range query](https://docs.victoriametrics.com/keyconcepts/#range-query)._
|
||||
* _[tlast_over_time](https://docs.victoriametrics.com/metricsql/#tlast_over_time) function returns last timestamp on
|
||||
the given look-behind window, similarly to [last_over_time](https://docs.victoriametrics.com/metricsql/#last_over_time)._
|
||||
* How do I get raw data points with MetricsQL?
|
||||
* _For getting raw data points specify the interval at which you want them in square brackets and send
|
||||
as [instant query](https://docs.victoriametrics.com/keyconcepts/#instant-query). For
|
||||
|
||||
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
@@ -31,6 +31,7 @@ git branch
|
||||
|
||||
* Make your changes and tests to the new branch.
|
||||
* Run command ``helm-docs`` to update content of ``README.md`` file of all charts using the ``README.md.gotmpl`` template.
|
||||
* Add a line to the ``CHANGELOG.md`` file of the modified chart with the changes made.
|
||||
* Commit the changes to the branch.
|
||||
* Push files to repository remote with command:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Next release
|
||||
|
||||
- TODO
|
||||
- vector chart 0.37.x -> 0.40.x
|
||||
|
||||
## 0.8.14
|
||||
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.15.6
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.15.5
|
||||
|
||||
**Release date:** 17 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.13.8
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.13.7
|
||||
|
||||
**Release date:** 17 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 1.7.2
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- Upgraded ['vmanomaly`](https://docs.victoriametrics.com/anomaly-detection/) to [1.19.2](https://docs.victoriametrics.com/anomaly-detection/changelog/#v1192).
|
||||
|
||||
## 1.7.1
|
||||
|
||||
**Release date:** 21 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.8.6
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.8.5
|
||||
|
||||
**Release date:** 17 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,22 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.17.4
|
||||
|
||||
**Release date:** 04 Feb 2025
|
||||
|
||||
 
|
||||
|
||||
- fixed service templates ports rendering when opentsdbListenAddr flag is set. See [this issue](https://github.com/VictoriaMetrics/helm-charts/issues/1961) for details.
|
||||
|
||||
## 0.17.3
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.17.2
|
||||
|
||||
**Release date:** 17 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.0.38
|
||||
|
||||
**Release date:** 04 Feb 2025
|
||||
|
||||

|
||||
|
||||
- Fixed minor securityContext template typo
|
||||
|
||||
## 0.0.37
|
||||
|
||||
**Release date:** 06 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.7.4
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.7.3
|
||||
|
||||
**Release date:** 17 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.6.6
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.6.5
|
||||
|
||||
**Release date:** 17 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -2,6 +2,63 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.35.5
|
||||
|
||||
**Release date:** 04 Feb 2025
|
||||
|
||||
 
|
||||
|
||||
- added `access` property to all default datasources
|
||||
|
||||
## 0.35.4
|
||||
|
||||
**Release date:** 04 Feb 2025
|
||||
|
||||
 
|
||||
|
||||
- add `.Values.defaultDatasources.grafanaOperator` section to manage datasources using Grafana operator. See [this issue](https://github.com/VictoriaMetrics/helm-charts/issues/1964) for details.
|
||||
- grafana chart 8.6.x -> 8.9.x
|
||||
- prometheus CRDs chart 16.x -> 17.x
|
||||
- kube-state-metrics chart 5.27.x -> 5.29.x
|
||||
- prometheus-node-exporter chart 4.42.x -> 4.43.x
|
||||
|
||||
## 0.35.3
|
||||
|
||||
**Release date:** 04 Feb 2025
|
||||
|
||||
 
|
||||
|
||||
- Use .Values.global.clusterLabel in rules annotations instead of `.cluster`
|
||||
|
||||
## 0.35.2
|
||||
|
||||
**Release date:** 31 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- Grafana datasource: do not verify allow_loading_unsigned_plugins in k8s-stack
|
||||
- Fixed configmap rendering for vmalert.templateFiles
|
||||
|
||||
## 0.35.1
|
||||
|
||||
**Release date:** 30 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- add `defaultDashboards.annotations` to `GrafanaDashboard`s resources.
|
||||
|
||||
## 0.35.0
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
**Update note**: This release contains breaking change. `.Values.externalVM` was renamed to `.Values.external.vm`
|
||||
|
||||
- add `.Values.external.grafana.host` to configure grafana host for alerts, when `.Values.grafana.enabled: false`
|
||||
- rename `.Values.externalVM` to `.Values.external.vm` for consistency
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.34.0
|
||||
|
||||
**Release date:** 22 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
@@ -836,16 +836,59 @@ perReplica: false
|
||||
<td><p>Configure additional grafana datasources (passed through tpl). Check <a href="http://docs.grafana.org/administration/provisioning/#datasources" target="_blank">here</a> for details</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultDatasources.grafanaOperator.annotations</td>
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">{}
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultDatasources.grafanaOperator.enabled</td>
|
||||
<td>bool</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="">
|
||||
<code class="language-yaml">false
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td><p>Create datasources as CRDs (requires grafana-operator to be installed)</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultDatasources.grafanaOperator.spec.allowCrossNamespaceImport</td>
|
||||
<td>bool</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="">
|
||||
<code class="language-yaml">false
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultDatasources.grafanaOperator.spec.instanceSelector.matchLabels.dashboards</td>
|
||||
<td>string</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="">
|
||||
<code class="language-yaml">grafana
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultDatasources.victoriametrics.datasources</td>
|
||||
<td>list</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">- isDefault: true
|
||||
<code class="language-yaml">- access: proxy
|
||||
isDefault: true
|
||||
name: VictoriaMetrics
|
||||
type: prometheus
|
||||
- isDefault: false
|
||||
- access: proxy
|
||||
isDefault: false
|
||||
name: VictoriaMetrics (DS)
|
||||
type: victoriametrics-datasource
|
||||
type: victoriametrics-metrics-datasource
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
@@ -1326,7 +1369,18 @@ vmsingle:
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>externalVM</td>
|
||||
<td>external.grafana</td>
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">host: grafana.external.host
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td><p>External Grafana host</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>external.vm</td>
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">read:
|
||||
@@ -2415,7 +2469,7 @@ tls: []
|
||||
<td>vmalert.spec</td>
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">evaluationInterval: 15s
|
||||
<code class="language-yaml">evaluationInterval: 20s
|
||||
externalLabels: {}
|
||||
extraArgs:
|
||||
http.pathPrefix: /
|
||||
@@ -2475,7 +2529,7 @@ unauthorizedUserAccessSpec:
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
<td><p>Full spec for VMAuth CRD. Allowed values described <a href="https://docs.victoriametrics.com/operator/api#vmauthspec" target="_blank">here</a> It’s possible to use given below predefined variables in spec: * <code>{{ .vm.read }}</code> - parsed vmselect, vmsingle or externalVM.read URL * <code>{{ .vm.write }}</code> - parsed vminsert, vmsingle or externalVM.write URL</p>
|
||||
<td><p>Full spec for VMAuth CRD. Allowed values described <a href="https://docs.victoriametrics.com/operator/api#vmauthspec" target="_blank">here</a> It’s possible to use given below predefined variables in spec: * <code>{{ .vm.read }}</code> - parsed vmselect, vmsingle or external.vm.read URL * <code>{{ .vm.write }}</code> - parsed vminsert, vmsingle or external.vm.write URL</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.41.1
|
||||
|
||||
**Release date:** 04 Feb 2025
|
||||
|
||||
 
|
||||
|
||||
- Added default values for securityContext and podSecurityContext
|
||||
|
||||
## 0.41.0
|
||||
|
||||
**Release date:** 22 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
@@ -259,6 +259,7 @@ Change the values according to the need of the environment in ``victoria-metrics
|
||||
commonName: ca.validation.victoriametrics
|
||||
duration: 63800h0m0s
|
||||
cert:
|
||||
commonName: ""
|
||||
duration: 45800h0m0s
|
||||
enabled: false
|
||||
issuer: {}
|
||||
@@ -294,6 +295,7 @@ tls:
|
||||
commonName: ca.validation.victoriametrics
|
||||
duration: 63800h0m0s
|
||||
cert:
|
||||
commonName: ""
|
||||
duration: 45800h0m0s
|
||||
enabled: false
|
||||
issuer: {}
|
||||
@@ -319,7 +321,8 @@ duration: 63800h0m0s
|
||||
<td>admissionWebhooks.certManager.cert</td>
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">duration: 45800h0m0s
|
||||
<code class="language-yaml">commonName: ""
|
||||
duration: 45800h0m0s
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
@@ -806,6 +809,9 @@ labels: {}
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">enabled: true
|
||||
fsGroup: 2000
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
@@ -933,7 +939,12 @@ view:
|
||||
<td>securityContext</td>
|
||||
<td>object</td>
|
||||
<td><pre class="helm-vars-default-value language-yaml" lang="plaintext">
|
||||
<code class="language-yaml">enabled: true
|
||||
<code class="language-yaml">allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
enabled: true
|
||||
readOnlyRootFilesystem: true
|
||||
</code>
|
||||
</pre>
|
||||
</td>
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
- TODO
|
||||
|
||||
## 0.13.8
|
||||
|
||||
**Release date:** 27 Jan 2025
|
||||
|
||||
 
|
||||
|
||||
- bump version of VM components to [v1.110.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.110.0)
|
||||
|
||||
## 0.13.7
|
||||
|
||||
**Release date:** 20 Jan 2025
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -34,11 +34,13 @@ the `request` was served. Label-value pairs are always of a `string` type. Victo
|
||||
which means there is no need to define metric names or their labels in advance. User is free to add or change ingested
|
||||
metrics anytime.
|
||||
|
||||
Actually, the metric name is also a label with a special name `__name__`. So the following two series are identical:
|
||||
Actually, the metric name is also a label with a special name `__name__`.
|
||||
The `__name__` key could be omitted {{% available_from "#" %}} for simplicity. So the following series are identical:
|
||||
|
||||
```
|
||||
requests_total{path="/", code="200"}
|
||||
{__name__="requests_total", path="/", code="200"}
|
||||
{"requests_total", path="/", code="200"}
|
||||
```
|
||||
|
||||
Labels can be automatically attached to the [time series](#time-series)
|
||||
|
||||
@@ -13,6 +13,24 @@ aliases:
|
||||
|
||||
## tip
|
||||
|
||||
## [v0.53.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.53.0)
|
||||
|
||||
**Release date:** 05 Feb 2025
|
||||
|
||||

|
||||

|
||||
|
||||
* SECURITY: upgrade Go builder from Go1.23.4 to Go1.23.5. See the list of issues addressed in [Go1.23.5](https://github.com/golang/go/issues?q=milestone%3AGo1.23.5+label%3ACherryPickApproved).
|
||||
|
||||
* Dependency: [vmoperator](https://docs.victoriametrics.com/operator/): Updated default versions for VM apps to v1.110.0 version
|
||||
|
||||
* FEATURE: [vmalertmanagerconfig](https://docs.victoriametrics.com/operator/resources/vmalertmanagerconfig/): add `thread_message_id` to `telegram_configs` definition. It's supported by [alertmanager v0.28.0+](https://github.com/prometheus/alertmanager/releases/tag/v0.28.0). See [this issue](https://github.com/VictoriaMetrics/operator/issues/1229) for details.
|
||||
* FEATURE: [vlogs](https://docs.victoriametrics.com/operator/resources/vlogs): support VLogs in VMUser targetRefs.crd
|
||||
|
||||
* BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): properly check `Pod` state during `StatefulSet` rolling upgrade procedure. See [this issue](https://github.com/VictoriaMetrics/operator/issues/1227) for details.
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/operator/resources/vmagent/): properly upscale on `shardCount` change. See [this issue](https://github.com/VictoriaMetrics/operator/issues/1224) for details.
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/operator/resources/vmauth/): properly apply `vmuser` changes. See [this PR](https://github.com/VictoriaMetrics/operator/pull/1231) for details.
|
||||
|
||||
## [v0.52.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.52.0)
|
||||
|
||||
**Release date:** 21 Jan 2025
|
||||
@@ -194,8 +212,8 @@ Operator will preserve `annotations`, but any changes to it will be ignored. `la
|
||||
- [api](https://docs.victoriametrics.com/operator): deletes unused env variables: `VM_DEFAULTLABELS`, `VM_PODWAITREADYINITDELAY`. Adds new variable `VM_APPREADYTIMEOUT`.
|
||||
- [vmalert](https://docs.victoriametrics.com/operator/resources/vmalert/): adds missing `hostAliases` fields to spec. See [this](https://github.com/VictoriaMetrics/operator/issues/1099) issue for details.
|
||||
- [vmsingle/vlogs](https://docs.victoriametrics.com/operator/resources): makes better compatible with argo-cd by adding ownerReference to PersistentVolumeClaim. See this [issue](https://github.com/VictoriaMetrics/operator/issues/1091) for details.
|
||||
- [operator](https://docs.victoriametrics.com/operator/): reduces reconcile latency. See this [commit](2a9d09d0131cc10a0f9e32f0e2e054687ada78f7) for details.
|
||||
- [operator](https://docs.victoriametrics.com/operator/): reduces load on kubernetes api-server. See this commits: [commit-0](a0145b8a89dd5bb9051f8d4359b6a70c1d1a95ce), [commit-1](e2fbbd3e37146670f656d700ad0f64b2c299b0a0), [commit-2](184ba19a5f1d10dc2ac1bf018b2729f64e2a8c25).
|
||||
- [operator](https://docs.victoriametrics.com/operator/): reduces reconcile latency. See this [commit](https://github.com/VictoriaMetrics/operator/commit/2a9d09d0131cc10a0f9e32f0e2e054687ada78f7) for details.
|
||||
- [operator](https://docs.victoriametrics.com/operator/): reduces load on kubernetes api-server. See this commits: [commit-0](https://github.com/VictoriaMetrics/operator/commit/a0145b8a89dd5bb9051f8d4359b6a70c1d1a95ce), [commit-1](https://github.com/VictoriaMetrics/operator/commit/e2fbbd3e37146670f656d700ad0f64b2c299b0a0), [commit-2](https://github.com/VictoriaMetrics/operator/commit/184ba19a5f1d10dc2ac1bf018b2729f64e2a8c25).
|
||||
- [operator](https://docs.victoriametrics.com/operator/): enables client cache back for `secrets` and `configmaps`. Adds new flag `-controller.disableCacheFor=secret,configmap` to disable it if needed.
|
||||
- [operator](https://docs.victoriametrics.com/operator/): made webhook port configurable. See [this issue](https://github.com/VictoriaMetrics/operator/issues/1106) for details.
|
||||
- [operator](https://docs.victoriametrics.com/operator/): operator trims spaces from `Secret` and `Configmap` values by default. This behaviour could be changed with flag `disableSecretKeySpaceTrim`. Related [issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6986).
|
||||
|
||||
@@ -2347,6 +2347,7 @@ _Appears in:_
|
||||
| `disable_notifications` | DisableNotifications | _boolean_ | false |
|
||||
| `http_config` | HTTP client configuration. | _[HTTPConfig](#httpconfig)_ | false |
|
||||
| `message` | Message is templated message | _string_ | false |
|
||||
| `message_thread_id` | MessageThreadID defines ID of the message thread where to send the messages. | _integer_ | false |
|
||||
| `parse_mode` | ParseMode for telegram message,<br />supported values are MarkdownV2, Markdown, Markdown and empty string for plain text. | _string_ | false |
|
||||
| `send_resolved` | SendResolved controls notify about resolved alerts. | _boolean_ | false |
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ aliases:
|
||||
- /operator/vars/index.html
|
||||
---
|
||||
<!-- this doc autogenerated - don't edit it manually -->
|
||||
updated at Tue Jan 21 09:58:31 UTC 2025
|
||||
updated at Tue Jan 28 08:41:50 UTC 2025
|
||||
|
||||
|
||||
| variable name | variable default value | variable required | variable description |
|
||||
@@ -31,7 +31,7 @@ aliases:
|
||||
| VM_VLOGSDEFAULT_CONFIGRELOADERCPU | - | false | ignored |
|
||||
| VM_VLOGSDEFAULT_CONFIGRELOADERMEMORY | - | false | ignored |
|
||||
| VM_VMALERTDEFAULT_IMAGE | victoriametrics/vmalert | false | - |
|
||||
| VM_VMALERTDEFAULT_VERSION | v1.109.1 | false | - |
|
||||
| VM_VMALERTDEFAULT_VERSION | v1.110.0 | false | - |
|
||||
| VM_VMALERTDEFAULT_CONFIGRELOADIMAGE | jimmidyson/configmap-reload:v0.3.0 | false | - |
|
||||
| VM_VMALERTDEFAULT_PORT | 8080 | false | - |
|
||||
| VM_VMALERTDEFAULT_USEDEFAULTRESOURCES | true | false | - |
|
||||
@@ -43,7 +43,7 @@ aliases:
|
||||
| VM_VMALERTDEFAULT_CONFIGRELOADERMEMORY | 25Mi | false | - |
|
||||
| VM_VMSERVICESCRAPEDEFAULT_ENFORCEENDPOINTSLICES | false | false | Use endpointslices instead of endpoints as discovery role for vmservicescrape when generate scrape config for vmagent. |
|
||||
| VM_VMAGENTDEFAULT_IMAGE | victoriametrics/vmagent | false | - |
|
||||
| VM_VMAGENTDEFAULT_VERSION | v1.109.1 | false | - |
|
||||
| VM_VMAGENTDEFAULT_VERSION | v1.110.0 | false | - |
|
||||
| VM_VMAGENTDEFAULT_CONFIGRELOADIMAGE | quay.io/prometheus-operator/prometheus-config-reloader:v0.68.0 | false | - |
|
||||
| VM_VMAGENTDEFAULT_PORT | 8429 | false | - |
|
||||
| VM_VMAGENTDEFAULT_USEDEFAULTRESOURCES | true | false | - |
|
||||
@@ -54,7 +54,7 @@ aliases:
|
||||
| VM_VMAGENTDEFAULT_CONFIGRELOADERCPU | 100m | false | - |
|
||||
| VM_VMAGENTDEFAULT_CONFIGRELOADERMEMORY | 25Mi | false | - |
|
||||
| VM_VMSINGLEDEFAULT_IMAGE | victoriametrics/victoria-metrics | false | - |
|
||||
| VM_VMSINGLEDEFAULT_VERSION | v1.109.1 | false | - |
|
||||
| VM_VMSINGLEDEFAULT_VERSION | v1.110.0 | false | - |
|
||||
| VM_VMSINGLEDEFAULT_CONFIGRELOADIMAGE | - | false | ignored |
|
||||
| VM_VMSINGLEDEFAULT_PORT | 8429 | false | - |
|
||||
| VM_VMSINGLEDEFAULT_USEDEFAULTRESOURCES | true | false | - |
|
||||
@@ -66,14 +66,14 @@ aliases:
|
||||
| VM_VMSINGLEDEFAULT_CONFIGRELOADERMEMORY | - | false | ignored |
|
||||
| VM_VMCLUSTERDEFAULT_USEDEFAULTRESOURCES | true | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_IMAGE | victoriametrics/vmselect | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_VERSION | v1.109.1-cluster | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_VERSION | v1.110.0-cluster | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_PORT | 8481 | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_LIMIT_MEM | 1000Mi | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_LIMIT_CPU | 500m | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_REQUEST_MEM | 500Mi | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_REQUEST_CPU | 100m | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_IMAGE | victoriametrics/vmstorage | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VERSION | v1.109.1-cluster | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VERSION | v1.110.0-cluster | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VMINSERTPORT | 8400 | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VMSELECTPORT | 8401 | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_PORT | 8482 | false | - |
|
||||
@@ -82,7 +82,7 @@ aliases:
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_RESOURCE_REQUEST_MEM | 500Mi | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_RESOURCE_REQUEST_CPU | 250m | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_IMAGE | victoriametrics/vminsert | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_VERSION | v1.109.1-cluster | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_VERSION | v1.110.0-cluster | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_PORT | 8480 | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_RESOURCE_LIMIT_MEM | 500Mi | false | - |
|
||||
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_RESOURCE_LIMIT_CPU | 500m | false | - |
|
||||
@@ -101,7 +101,7 @@ aliases:
|
||||
| VM_VMALERTMANAGER_RESOURCE_REQUEST_CPU | 30m | false | - |
|
||||
| VM_DISABLESELFSERVICESCRAPECREATION | false | false | - |
|
||||
| VM_VMBACKUP_IMAGE | victoriametrics/vmbackupmanager | false | - |
|
||||
| VM_VMBACKUP_VERSION | v1.109.1-enterprise | false | - |
|
||||
| VM_VMBACKUP_VERSION | v1.110.0-enterprise | false | - |
|
||||
| VM_VMBACKUP_PORT | 8300 | false | - |
|
||||
| VM_VMBACKUP_USEDEFAULTRESOURCES | true | false | - |
|
||||
| VM_VMBACKUP_RESOURCE_LIMIT_MEM | 500Mi | false | - |
|
||||
@@ -109,7 +109,7 @@ aliases:
|
||||
| VM_VMBACKUP_RESOURCE_REQUEST_MEM | 200Mi | false | - |
|
||||
| VM_VMBACKUP_RESOURCE_REQUEST_CPU | 150m | false | - |
|
||||
| VM_VMAUTHDEFAULT_IMAGE | victoriametrics/vmauth | false | - |
|
||||
| VM_VMAUTHDEFAULT_VERSION | v1.109.1 | false | - |
|
||||
| VM_VMAUTHDEFAULT_VERSION | v1.110.0 | false | - |
|
||||
| VM_VMAUTHDEFAULT_CONFIGRELOADIMAGE | quay.io/prometheus-operator/prometheus-config-reloader:v0.68.0 | false | - |
|
||||
| VM_VMAUTHDEFAULT_PORT | 8427 | false | - |
|
||||
| VM_VMAUTHDEFAULT_USEDEFAULTRESOURCES | true | false | - |
|
||||
@@ -137,4 +137,4 @@ aliases:
|
||||
| VM_PODWAITREADYINTERVALCHECK | 5s | false | Defines poll interval for pods ready check at statefulset rollout update |
|
||||
| VM_FORCERESYNCINTERVAL | 60s | false | configures force resync interval for VMAgent, VMAlert, VMAlertmanager and VMAuth. |
|
||||
| VM_ENABLESTRICTSECURITY | false | false | EnableStrictSecurity will add default `securityContext` to pods and containers created by operator Default PodSecurityContext include: 1. RunAsNonRoot: true 2. RunAsUser/RunAsGroup/FSGroup: 65534 '65534' refers to 'nobody' in all the used default images like alpine, busybox. If you're using customize image, please make sure '65534' is a valid uid in there or specify SecurityContext. 3. FSGroupChangePolicy: &onRootMismatch If KubeVersion>=1.20, use `FSGroupChangePolicy="onRootMismatch"` to skip the recursive permission change when the root of the volume already has the correct permissions 4. SeccompProfile: type: RuntimeDefault Use `RuntimeDefault` seccomp profile by default, which is defined by the container runtime, instead of using the Unconfined (seccomp disabled) mode. Default container SecurityContext include: 1. AllowPrivilegeEscalation: false 2. ReadOnlyRootFilesystem: true 3. Capabilities: drop: - all turn off `EnableStrictSecurity` by default, see https://github.com/VictoriaMetrics/operator/issues/749 for details |
|
||||
[envconfig-sum]: d608f780f1899e181a90c544575832ef
|
||||
[envconfig-sum]: bdcf894ae7e977c74390de77b464dd65
|
||||
@@ -297,12 +297,12 @@ metrics with different `vmrange` or `le` labels. As they're counters, the applic
|
||||
This config generates the following output metrics according to [output metric naming](#output-metric-names):
|
||||
|
||||
```text
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="0.1"} value1
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="0.2"} value2
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="0.4"} value3
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="1"} value4
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="3"} value5
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="+Inf" value6
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="0.1"} value1
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="0.2"} value2
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="0.4"} value3
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="1"} value4
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="3"} value5
|
||||
http_request_duration_seconds_bucket:1m_without_instance_total{le="+Inf"} value6
|
||||
```
|
||||
|
||||
The resulting metrics can be passed to [histogram_quantile](https://docs.victoriametrics.com/metricsql/#histogram_quantile)
|
||||
@@ -1261,4 +1261,4 @@ across multiple `-remoteWrite.url`.
|
||||
|
||||
Stream aggregation allows keeping original metric names after aggregation by using `keep_metric_names` setting.
|
||||
But the "meaning" of aggregated metrics is usually different to original ones after the aggregation.
|
||||
Make sure that you updated queries in your alerting rules and dashboards accordingly if you used `keep_metric_names` setting.
|
||||
Make sure that you updated queries in your alerting rules and dashboards accordingly if you used `keep_metric_names` setting.
|
||||
|
||||
@@ -18,9 +18,9 @@ This guide explains the different ways in which you can use vmalert in conjuncti
|
||||
|
||||
* [vmalert](https://docs.victoriametrics.com/vmalert/) is installed. You can obtain it by building it from [source](https://docs.victoriametrics.com/vmalert/#quickstart), downloading it from the [GitHub releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest), or using the [docker image](https://hub.docker.com/r/victoriametrics/vmalert) for the container ecosystem (such as docker, k8s, etc.).
|
||||
* [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) is installed.
|
||||
* You have a [single or cluster](https://docs.victoriametrics.com/victoriametrics-cloud/quickstart.html#creating-deployment) deployment in [VictoriaMetrics Cloud](https://docs.victoriametrics.com/victoriametrics-cloud/overview.html).
|
||||
* If you are using helm, add the [VictoriaMetrics helm chart](https://github.com/VictoriaMetrics/helm-charts/tree/master/charts/victoria-metrics-alert#how-to-install) repository to your helm repositories. This step is optional.
|
||||
* If you are using [vmoperator](https://docs.victoriametrics.com/operator/quick-start.html#quick-start), make sure that it and its CRDs are installed. This step is also optional.
|
||||
* You have a [single or cluster](https://docs.victoriametrics.com/victoriametrics-cloud/quickstart/#creating-deployment) deployment in [VictoriaMetrics Cloud](https://docs.victoriametrics.com/victoriametrics-cloud/overview/).
|
||||
* If you are using helm, add the [VictoriaMetrics helm chart](https://docs.victoriametrics.com/helm/victoriametrics-alert#how-to-install) repository to your helm repositories. This step is optional.
|
||||
* If you are using [vmoperator](https://docs.victoriametrics.com/operator/quick-start/#quick-start), make sure that it and its CRDs are installed. This step is also optional.
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -50,7 +50,7 @@ groups:
|
||||
|
||||
To use vmalert with VictoriaMetrics Cloud, you must create a read/write token, or use an existing one. The token must have write access to ingest recording rules, ALERTS and ALERTS_FOR_STATE metrics, and read access for rules evaluation.
|
||||
|
||||
For instructions on how to create tokens, please refer to this section of the [documentation](https://docs.victoriametrics.com/victoriametrics-cloud/quickstart.html#deployment-access).
|
||||
For instructions on how to create tokens, please refer to this section of the [documentation](https://docs.victoriametrics.com/victoriametrics-cloud/quickstart/#deployment-access).
|
||||
|
||||
#### Single-Node
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Monitoring kubernetes cluster is necessary to build SLO/SLI, to analyze performa
|
||||
To enable kubernetes cluster monitoring, we will be collecting metrics about cluster performance and utilization from kubernetes components like `kube-api-server`, `kube-controller-manager`, `kube-scheduler`, `kube-state-metrics`, `etcd`, `core-dns`, `kubelet` and `kube-proxy`. We will also install some recording rules, alert rules and dashboards to provide visibility of cluster performance, as well as alerting for cluster metrics.
|
||||
For node resource utilization we will be collecting metrics from `node-exporter`. We will also install dashboard and alerts for node related metrics
|
||||
|
||||
For workloads monitoring in kubernetes cluster we will have [VictoriaMetrics Operator](https://docs.victoriametrics.com/operator/VictoriaMetrics-Operator.html). It enables us to define scrape jobs using kubernetes CRDs [VMServiceScrape](https://docs.victoriametrics.com/operator/design.html#vmservicescrape), [VMPodScrape](https://docs.victoriametrics.com/operator/design.html#vmpodscrape). To add alerts or recording rules for workloads we can use [VMRule](https://docs.victoriametrics.com/operator/design.html#vmrule) CRD
|
||||
For workloads monitoring in kubernetes cluster we will have [VictoriaMetrics Operator](https://docs.victoriametrics.com/operator/). It enables us to define scrape jobs using kubernetes CRDs [VMServiceScrape](https://docs.victoriametrics.com/operator/design.html#vmservicescrape), [VMPodScrape](https://docs.victoriametrics.com/operator/design.html#vmpodscrape). To add alerts or recording rules for workloads we can use [VMRule](https://docs.victoriametrics.com/operator/design.html#vmrule) CRD
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user