mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-05-22 19:26:35 +03:00
Compare commits
32 Commits
ark/implem
...
per-aggreg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c71a9478f0 | ||
|
|
efd70b2c52 | ||
|
|
cda6a31ae8 | ||
|
|
c6e7fb688b | ||
|
|
ef01df10bd | ||
|
|
798256a655 | ||
|
|
c8bc2f0ee5 | ||
|
|
9c0871786f | ||
|
|
94ad22d140 | ||
|
|
45794de0f9 | ||
|
|
65bb429b81 | ||
|
|
66a34acc3a | ||
|
|
ea5c3571e9 | ||
|
|
bcbfea56f9 | ||
|
|
6a12d2f18b | ||
|
|
1e8987df29 | ||
|
|
e5beeb18d3 | ||
|
|
e78a51bf39 | ||
|
|
aefc4538bd | ||
|
|
1f96882367 | ||
|
|
65ce4e30ab | ||
|
|
eaed0465d2 | ||
|
|
9c4b0334f2 | ||
|
|
8ff051b287 | ||
|
|
74affa3aec | ||
|
|
58a757cd01 | ||
|
|
bdc0e688e8 | ||
|
|
6f9f861f57 | ||
|
|
7ed719b46a | ||
|
|
7ee5797493 | ||
|
|
277aad18d8 | ||
|
|
ad6af95183 |
42
README.md
42
README.md
@@ -699,23 +699,21 @@ Example for writing data with Graphite plaintext protocol to local VictoriaMetri
|
||||
echo "foo.bar.baz;tag1=value1;tag2=value2 123 `date +%s`" | nc -N localhost 2003
|
||||
```
|
||||
|
||||
To sanitize ingested metric names and labels according to Prometheus naming convention enable
|
||||
`-graphite.sanitizeMetricName` cmd-line flag. When enabled, VictoriaMetrics will apply the following modifications:
|
||||
- replace `/`,`@`,`*` with `_`;
|
||||
- drop `\`;
|
||||
- remove redundant dots, e.g: `metric..name` => `metric.name`;
|
||||
- replace characters not matching the expression `^a-zA-Z0-9:._` with `_`.
|
||||
The ingested metrics can be sanitized according to Prometheus naming convention by passing `-graphite.sanitizeMetricName` command-line flag
|
||||
to VictoriaMetrics. The following modifications are applied to the ingested samples when this flag is passed to VictoriaMetrics:
|
||||
|
||||
- remove redundant dots, e.g: `metric..name` => `metric.name`
|
||||
- replace characters not matching `a-zA-Z0-9:_.` chars with `_`
|
||||
|
||||
VictoriaMetrics sets the current time to the ingested samples if the timestamp is omitted.
|
||||
|
||||
VictoriaMetrics sets the current time if the timestamp is omitted.
|
||||
An arbitrary number of lines delimited by `\n` (aka newline char) can be sent in one go.
|
||||
After that the data may be read via [/api/v1/export](#how-to-export-data-in-json-line-format) endpoint:
|
||||
|
||||
|
||||
```sh
|
||||
curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz'
|
||||
```
|
||||
|
||||
|
||||
The `/api/v1/export` endpoint should return the following response:
|
||||
|
||||
```json
|
||||
@@ -2645,24 +2643,30 @@ It is built from `*.md` files located in [docs](https://github.com/VictoriaMetri
|
||||
and gets automatically updated once changes are merged to [master](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master) branch.
|
||||
To update the documentation follow the steps below:
|
||||
- [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks)
|
||||
VictoriaMetrics repo and apply changes to the docs:
|
||||
VictoriaMetrics repo and apply changes to the docs:
|
||||
- To update [the main page](https://docs.victoriametrics.com/) modify [this file](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md).
|
||||
- To update other pages, apply changes to the corresponding file in [docs folder](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/docs).
|
||||
- If your changes contain an image then see [images in documentation](https://docs.victoriametrics.com/#images-in-documentation).
|
||||
- Once changes are made, execute the command below to finalize and sync the changes:
|
||||
```sh
|
||||
make docs-sync
|
||||
```
|
||||
|
||||
```sh
|
||||
make docs-sync
|
||||
```
|
||||
|
||||
- Create [a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
|
||||
with proposed changes and wait for it to be merged.
|
||||
with proposed changes and wait for it to be merged.
|
||||
|
||||
Requirements for changes to docs:
|
||||
|
||||
- Keep backward compatibility of existing links. Avoid changing anchors or deleting pages as they could have been
|
||||
used or posted in other docs, GitHub issues, stackoverlow answers, etc.
|
||||
- Keep docs simple. Try using as simple wording as possible.
|
||||
used or posted in other docs, GitHub issues, stackoverlow answers, etc.
|
||||
- Keep docs clear, concise and simple. Try using as simple wording as possible, without loosing the clarity.
|
||||
- Keep docs consistent. When modifying existing docs, verify that other places referencing to this doc are still relevant.
|
||||
- Prefer improving the existing docs instead of adding new ones.
|
||||
- Use absolute links.
|
||||
- Use absolute links. This simplifies moving docs between different files.
|
||||
|
||||
Priodically run `make spellcheck` - this command detects spelling errors at `docs/` folder. Please fix the found spelling errors
|
||||
and commit the fixes in a separate commit.
|
||||
|
||||
### Images in documentation
|
||||
|
||||
@@ -2670,6 +2674,10 @@ Please, keep image size and number of images per single page low. Keep the docs
|
||||
|
||||
Image files must be placed in the same folder as the doc itself and they must have the same prefix as the doc filename.
|
||||
For example, all the images for `docs/foo/bar.md` should have filenames starting from `docs/foo/bar`.
|
||||
This simplifies lifetime management of the images:
|
||||
|
||||
- when the corresponding doc is removed, then it is clear how to remove the associated images
|
||||
- when the corresponding doc is renamed, then it is clear how to rename the associated images.
|
||||
|
||||
If the page needs to have many images, consider using WEB-optimized image format [webp](https://developers.google.com/speed/webp).
|
||||
When adding a new doc with many images use `webp` format right away. Or use a Makefile command below to
|
||||
|
||||
@@ -230,7 +230,7 @@ func generateLogsAtTimestamp(bw *bufio.Writer, workerID int, ts int64, firstStre
|
||||
for i := 0; i < activeStreams; i++ {
|
||||
ip := toIPv4(rand.Uint32())
|
||||
uuid := toUUID(rand.Uint64(), rand.Uint64())
|
||||
fmt.Fprintf(bw, `{"_time":%q,"_msg":"message for the stream %d and worker %d; ip=%s; uuid=%s; u64=%d","host":"host_%d","worker_id":"%d"`,
|
||||
fmt.Fprintf(bw, `{"_time":"%s","_msg":"message for the stream %d and worker %d; ip=%s; uuid=%s; u64=%d","host":"host_%d","worker_id":"%d"`,
|
||||
timeStr, streamID, workerID, ip, uuid, rand.Uint64(), streamID, workerID)
|
||||
fmt.Fprintf(bw, `,"run_id":"%s"`, runID)
|
||||
for j := 0; j < *constFieldsPerLog; j++ {
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/csvimport"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/datadogsketches"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmagent/datadogv1"
|
||||
@@ -42,7 +44,7 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/opentelemetry/firehose"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/pushmetrics"
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -450,7 +452,7 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var bb bytesutil.ByteBuffer
|
||||
promscrape.WriteConfigData(&bb)
|
||||
fmt.Fprintf(w, `{"status":"success","data":{"yaml":%q}}`, bb.B)
|
||||
fmt.Fprintf(w, `{"status":"success","data":{"yaml":%s}}`, stringsutil.JSONString(string(bb.B)))
|
||||
return true
|
||||
case "/prometheus/-/reload", "/-/reload":
|
||||
if !httpserver.CheckAuthFlag(w, r, reloadAuthKey) {
|
||||
|
||||
@@ -488,12 +488,7 @@ func tryPush(at *auth.Token, wr *prompbmarshal.WriteRequest, forceDropSamplesOnF
|
||||
sortLabelsIfNeeded(tssBlock)
|
||||
tssBlock = limitSeriesCardinality(tssBlock)
|
||||
if sas.IsEnabled() {
|
||||
matchIdxs := matchIdxsPool.Get()
|
||||
matchIdxs.B = sas.Push(tssBlock, matchIdxs.B)
|
||||
if !*streamAggrGlobalKeepInput {
|
||||
tssBlock = dropAggregatedSeries(tssBlock, matchIdxs.B, *streamAggrGlobalDropInput)
|
||||
}
|
||||
matchIdxsPool.Put(matchIdxs)
|
||||
tssBlock = sas.Push(tssBlock)
|
||||
} else if deduplicatorGlobal != nil {
|
||||
deduplicatorGlobal.Push(tssBlock)
|
||||
tssBlock = tssBlock[:0]
|
||||
@@ -764,9 +759,6 @@ type remoteWriteCtx struct {
|
||||
sas atomic.Pointer[streamaggr.Aggregators]
|
||||
deduplicator *streamaggr.Deduplicator
|
||||
|
||||
streamAggrKeepInput bool
|
||||
streamAggrDropInput bool
|
||||
|
||||
pss []*pendingSeries
|
||||
pssNextIdx atomic.Uint64
|
||||
|
||||
@@ -910,18 +902,13 @@ func (rwctx *remoteWriteCtx) TryPush(tss []prompbmarshal.TimeSeries, forceDropSa
|
||||
// Apply stream aggregation or deduplication if they are configured
|
||||
sas := rwctx.sas.Load()
|
||||
if sas.IsEnabled() {
|
||||
matchIdxs := matchIdxsPool.Get()
|
||||
matchIdxs.B = sas.Push(tss, matchIdxs.B)
|
||||
if !rwctx.streamAggrKeepInput {
|
||||
if rctx == nil {
|
||||
rctx = getRelabelCtx()
|
||||
// Make a copy of tss before dropping aggregated series
|
||||
v = tssPool.Get().(*[]prompbmarshal.TimeSeries)
|
||||
tss = append(*v, tss...)
|
||||
}
|
||||
tss = dropAggregatedSeries(tss, matchIdxs.B, rwctx.streamAggrDropInput)
|
||||
if sas.ExpectModifications() && rctx == nil {
|
||||
rctx = getRelabelCtx()
|
||||
// Make a copy of tss before dropping aggregated series
|
||||
v = tssPool.Get().(*[]prompbmarshal.TimeSeries)
|
||||
tss = append(*v, tss...)
|
||||
}
|
||||
matchIdxsPool.Put(matchIdxs)
|
||||
tss = sas.Push(tss)
|
||||
} else if rwctx.deduplicator != nil {
|
||||
rwctx.deduplicator.Push(tss)
|
||||
return true
|
||||
@@ -942,23 +929,6 @@ func (rwctx *remoteWriteCtx) TryPush(tss []prompbmarshal.TimeSeries, forceDropSa
|
||||
return false
|
||||
}
|
||||
|
||||
var matchIdxsPool bytesutil.ByteBufferPool
|
||||
|
||||
func dropAggregatedSeries(src []prompbmarshal.TimeSeries, matchIdxs []byte, dropInput bool) []prompbmarshal.TimeSeries {
|
||||
dst := src[:0]
|
||||
if !dropInput {
|
||||
for i, match := range matchIdxs {
|
||||
if match == 1 {
|
||||
continue
|
||||
}
|
||||
dst = append(dst, src[i])
|
||||
}
|
||||
}
|
||||
tail := src[len(dst):]
|
||||
clear(tail)
|
||||
return dst
|
||||
}
|
||||
|
||||
func (rwctx *remoteWriteCtx) pushInternalTrackDropped(tss []prompbmarshal.TimeSeries) {
|
||||
if rwctx.tryPushInternal(tss) {
|
||||
return
|
||||
|
||||
@@ -70,8 +70,6 @@ func TestRemoteWriteContext_TryPush_ImmutableTimeseries(t *testing.T) {
|
||||
pss[0] = newPendingSeries(nil, true, 0, 100)
|
||||
rwctx := &remoteWriteCtx{
|
||||
idx: 0,
|
||||
streamAggrKeepInput: keepInput,
|
||||
streamAggrDropInput: dropInput,
|
||||
pss: pss,
|
||||
rowsPushedAfterRelabel: metrics.GetOrCreateCounter(`foo`),
|
||||
rowsDroppedByRelabel: metrics.GetOrCreateCounter(`bar`),
|
||||
|
||||
@@ -50,8 +50,7 @@ var (
|
||||
streamAggrIgnoreOldSamples = flagutil.NewArrayBool("remoteWrite.streamAggr.ignoreOldSamples", "Whether to ignore input samples with old timestamps outside the current "+
|
||||
"aggregation interval for the corresponding -remoteWrite.streamAggr.config at the corresponding -remoteWrite.url. "+
|
||||
"See https://docs.victoriametrics.com/stream-aggregation/#ignoring-old-samples")
|
||||
streamAggrIgnoreFirstIntervals = flag.Int("remoteWrite.streamAggr.ignoreFirstIntervals", 0, "Number of aggregation intervals to skip after the start "+
|
||||
"for the corresponding -remoteWrite.streamAggr.config at the corresponding -remoteWrite.url. Increase this value if "+
|
||||
streamAggrIgnoreFirstIntervals = flagutil.NewArrayInt("remoteWrite.streamAggr.ignoreFirstIntervals", 0, "Number of aggregation intervals to skip after the start "+"for the corresponding -remoteWrite.streamAggr.config at the corresponding -remoteWrite.url. Increase this value if "+
|
||||
"you observe incorrect aggregation results after vmagent restarts. It could be caused by receiving bufferred delayed data from clients pushing data into the vmagent. "+
|
||||
"See https://docs.victoriametrics.com/stream-aggregation/#ignore-aggregation-intervals-on-start")
|
||||
streamAggrDropInputLabels = flagutil.NewArrayString("remoteWrite.streamAggr.dropInputLabels", "An optional list of labels to drop from samples "+
|
||||
@@ -148,8 +147,6 @@ func (rwctx *remoteWriteCtx) initStreamAggrConfig() {
|
||||
if sas != nil {
|
||||
filePath := sas.FilePath()
|
||||
rwctx.sas.Store(sas)
|
||||
rwctx.streamAggrKeepInput = streamAggrKeepInput.GetOptionalArg(idx)
|
||||
rwctx.streamAggrDropInput = streamAggrDropInput.GetOptionalArg(idx)
|
||||
metrics.GetOrCreateCounter(fmt.Sprintf(`vmagent_streamaggr_config_reload_successful{path=%q}`, filePath)).Set(1)
|
||||
metrics.GetOrCreateCounter(fmt.Sprintf(`vmagent_streamaggr_config_reload_success_timestamp_seconds{path=%q}`, filePath)).Set(fasttime.UnixTimestamp())
|
||||
} else {
|
||||
@@ -202,6 +199,8 @@ func newStreamAggrConfigGlobal() (*streamaggr.Aggregators, error) {
|
||||
DropInputLabels: *streamAggrGlobalDropInputLabels,
|
||||
IgnoreOldSamples: *streamAggrGlobalIgnoreOldSamples,
|
||||
IgnoreFirstIntervals: *streamAggrGlobalIgnoreFirstIntervals,
|
||||
KeepInput: *streamAggrGlobalKeepInput,
|
||||
DropInput: *streamAggrGlobalDropInput,
|
||||
}
|
||||
|
||||
sas, err := streamaggr.LoadFromFile(path, pushToRemoteStoragesTrackDropped, opts, "global")
|
||||
@@ -229,7 +228,9 @@ func newStreamAggrConfigPerURL(idx int, pushFunc streamaggr.PushFunc) (*streamag
|
||||
DedupInterval: streamAggrDedupInterval.GetOptionalArg(idx),
|
||||
DropInputLabels: *streamAggrDropInputLabels,
|
||||
IgnoreOldSamples: streamAggrIgnoreOldSamples.GetOptionalArg(idx),
|
||||
IgnoreFirstIntervals: *streamAggrIgnoreFirstIntervals,
|
||||
IgnoreFirstIntervals: streamAggrIgnoreFirstIntervals.GetOptionalArg(idx),
|
||||
KeepInput: streamAggrKeepInput.GetOptionalArg(idx),
|
||||
DropInput: streamAggrDropInput.GetOptionalArg(idx),
|
||||
}
|
||||
|
||||
sas, err := streamaggr.LoadFromFile(path, pushFunc, opts, alias)
|
||||
|
||||
@@ -83,7 +83,9 @@ type UserInfo struct {
|
||||
|
||||
concurrencyLimitCh chan struct{}
|
||||
concurrencyLimitReached *metrics.Counter
|
||||
overrideHostHeader bool
|
||||
|
||||
// Whether to use backend host header in requests to backend.
|
||||
useBackendHostHeader bool
|
||||
|
||||
rt http.RoundTripper
|
||||
|
||||
@@ -150,7 +152,7 @@ func (h *Header) MarshalYAML() (any, error) {
|
||||
return h.sOriginal, nil
|
||||
}
|
||||
|
||||
func overrideHostHeader(headers []*Header) bool {
|
||||
func hasEmptyHostHeader(headers []*Header) bool {
|
||||
for _, h := range headers {
|
||||
if h.Name == "Host" && h.Value == "" {
|
||||
return true
|
||||
@@ -310,12 +312,18 @@ func (up *URLPrefix) getBackendsCount() int {
|
||||
|
||||
// getBackendURL returns the backendURL depending on the load balance policy.
|
||||
//
|
||||
// It can return nil if there are no backend urls available at the moment.
|
||||
//
|
||||
// backendURL.put() must be called on the returned backendURL after the request is complete.
|
||||
func (up *URLPrefix) getBackendURL() *backendURL {
|
||||
up.discoverBackendAddrsIfNeeded()
|
||||
|
||||
pbus := up.bus.Load()
|
||||
bus := *pbus
|
||||
if len(bus) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if up.loadBalancingPolicy == "first_available" {
|
||||
return getFirstAvailableBackendURL(bus)
|
||||
}
|
||||
@@ -397,7 +405,7 @@ func (up *URLPrefix) discoverBackendAddrsIfNeeded() {
|
||||
buCopy.Host = addr
|
||||
if port != "" {
|
||||
if n := strings.IndexByte(buCopy.Host, ':'); n >= 0 {
|
||||
// Drop the discovered port and substitute it the the port specified in bu.
|
||||
// Drop the discovered port and substitute it the port specified in bu.
|
||||
buCopy.Host = buCopy.Host[:n]
|
||||
}
|
||||
buCopy.Host += ":" + port
|
||||
@@ -741,7 +749,7 @@ func parseAuthConfig(data []byte) (*AuthConfig, error) {
|
||||
if err := ui.initURLs(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ui.overrideHostHeader = overrideHostHeader(ui.HeadersConf.RequestHeaders)
|
||||
ui.useBackendHostHeader = hasEmptyHostHeader(ui.HeadersConf.RequestHeaders)
|
||||
|
||||
metricLabels, err := ui.getMetricLabels()
|
||||
if err != nil {
|
||||
@@ -806,7 +814,7 @@ func parseAuthConfigUsers(ac *AuthConfig) (map[string]*UserInfo, error) {
|
||||
_ = ac.ms.GetOrCreateGauge(`vmauth_user_concurrent_requests_current`+metricLabels, func() float64 {
|
||||
return float64(len(ui.concurrencyLimitCh))
|
||||
})
|
||||
ui.overrideHostHeader = overrideHostHeader(ui.HeadersConf.RequestHeaders)
|
||||
ui.useBackendHostHeader = hasEmptyHostHeader(ui.HeadersConf.RequestHeaders)
|
||||
|
||||
rt, err := newRoundTripper(ui.TLSCAFile, ui.TLSCertFile, ui.TLSKeyFile, ui.TLSServerName, ui.TLSInsecureSkipVerify)
|
||||
if err != nil {
|
||||
|
||||
@@ -50,7 +50,7 @@ var (
|
||||
`Such requests are always counted at vmauth_http_request_errors_total{reason="invalid_auth_token"} metric, which is exposed at /metrics page`)
|
||||
failTimeout = flag.Duration("failTimeout", 3*time.Second, "Sets a delay period for load balancing to skip a malfunctioning backend")
|
||||
maxRequestBodySizeToRetry = flagutil.NewBytes("maxRequestBodySizeToRetry", 16*1024, "The maximum request body size, which can be cached and re-tried at other backends. "+
|
||||
"Bigger values may require more memory. Negative or zero values disable request body caching and retries.")
|
||||
"Bigger values may require more memory. Zero or negative value disables caching of request body. This may be useful when proxying data ingestion requests")
|
||||
backendTLSInsecureSkipVerify = flag.Bool("backend.tlsInsecureSkipVerify", false, "Whether to skip TLS verification when connecting to backends over HTTPS. "+
|
||||
"See https://docs.victoriametrics.com/vmauth/#backend-tls-setup")
|
||||
backendTLSCAFile = flag.String("backend.TLSCAFile", "", "Optional path to TLS root CA file, which is used for TLS verification when connecting to backends over HTTPS. "+
|
||||
@@ -200,15 +200,17 @@ func processRequest(w http.ResponseWriter, r *http.Request, ui *UserInfo) {
|
||||
up, hc = ui.DefaultURL, ui.HeadersConf
|
||||
isDefault = true
|
||||
}
|
||||
// caching makes sense only for positive non zero size
|
||||
if maxRequestBodySizeToRetry.IntN() > 0 {
|
||||
rtb := getReadTrackingBody(r.Body, int(r.ContentLength))
|
||||
defer putReadTrackingBody(rtb)
|
||||
r.Body = rtb
|
||||
}
|
||||
|
||||
rtb := getReadTrackingBody(r.Body, maxRequestBodySizeToRetry.IntN())
|
||||
defer putReadTrackingBody(rtb)
|
||||
r.Body = rtb
|
||||
|
||||
maxAttempts := up.getBackendsCount()
|
||||
for i := 0; i < maxAttempts; i++ {
|
||||
bu := up.getBackendURL()
|
||||
if bu == nil {
|
||||
break
|
||||
}
|
||||
targetURL := bu.url
|
||||
// Don't change path and add request_path query param for default route.
|
||||
if isDefault {
|
||||
@@ -238,7 +240,7 @@ func tryProcessingRequest(w http.ResponseWriter, r *http.Request, targetURL *url
|
||||
req := sanitizeRequestHeaders(r)
|
||||
req.URL = targetURL
|
||||
|
||||
if req.URL.Scheme == "https" || ui.overrideHostHeader {
|
||||
if req.URL.Scheme == "https" || ui.useBackendHostHeader {
|
||||
// Override req.Host only for https requests, since https server verifies hostnames during TLS handshake,
|
||||
// so it expects the targetURL.Host in the request.
|
||||
// There is no need in overriding the req.Host for http requests, since it is expected that backend server
|
||||
@@ -272,7 +274,7 @@ again:
|
||||
ui.backendErrors.Inc()
|
||||
return true
|
||||
}
|
||||
// one time retry trivial network errors, such as proxy idle timeout misconfiguration or socket close by OS
|
||||
// Retry request on trivial network errors, such as proxy idle timeout misconfiguration or socket close by OS
|
||||
if (netutil.IsTrivialNetworkError(err) || errors.Is(err, io.EOF)) && trivialRetries < 1 {
|
||||
trivialRetries++
|
||||
goto again
|
||||
@@ -490,85 +492,110 @@ func handleConcurrencyLimitError(w http.ResponseWriter, r *http.Request, err err
|
||||
httpserver.Errorf(w, r, "%s", err)
|
||||
}
|
||||
|
||||
// readTrackingBody must be obtained via getReadTrackingBody()
|
||||
type readTrackingBody struct {
|
||||
// maxBodySize is the maximum body size to cache in buf.
|
||||
//
|
||||
// Bigger bodies cannot be retried.
|
||||
maxBodySize int
|
||||
|
||||
// r contains reader for initial data reading
|
||||
r io.ReadCloser
|
||||
|
||||
// buf is a buffer for data read from r. Buf size is limited by maxRequestBodySizeToRetry.
|
||||
// If more than maxRequestBodySizeToRetry is read from r, then cannotRetry is set to true.
|
||||
// buf is a buffer for data read from r. Buf size is limited by maxBodySize.
|
||||
// If more than maxBodySize is read from r, then cannotRetry is set to true.
|
||||
buf []byte
|
||||
|
||||
// cannotRetry is set to true when more than maxRequestBodySizeToRetry are read from r.
|
||||
// readBuf points to the cached data at buf, which must be read in the next call to Read().
|
||||
readBuf []byte
|
||||
|
||||
// cannotRetry is set to true when more than maxBodySize bytes are read from r.
|
||||
// In this case the read data cannot fit buf, so it cannot be re-read from buf.
|
||||
cannotRetry bool
|
||||
|
||||
// bufComplete is set to true when buf contains complete request body read from r.
|
||||
bufComplete bool
|
||||
|
||||
// offset is an offset at buf for the next data read if needReadBuf is set to true.
|
||||
offset int
|
||||
}
|
||||
|
||||
// Read implements io.Reader interface
|
||||
// tracks body reading requests
|
||||
func (rtb *readTrackingBody) reset() {
|
||||
rtb.maxBodySize = 0
|
||||
rtb.r = nil
|
||||
rtb.buf = rtb.buf[:0]
|
||||
rtb.readBuf = nil
|
||||
rtb.cannotRetry = false
|
||||
rtb.bufComplete = false
|
||||
}
|
||||
|
||||
func getReadTrackingBody(r io.ReadCloser, maxBodySize int) *readTrackingBody {
|
||||
v := readTrackingBodyPool.Get()
|
||||
if v == nil {
|
||||
v = &readTrackingBody{}
|
||||
}
|
||||
rtb := v.(*readTrackingBody)
|
||||
|
||||
if maxBodySize < 0 {
|
||||
maxBodySize = 0
|
||||
}
|
||||
rtb.maxBodySize = maxBodySize
|
||||
rtb.r = r
|
||||
return rtb
|
||||
}
|
||||
|
||||
func putReadTrackingBody(rtb *readTrackingBody) {
|
||||
rtb.reset()
|
||||
readTrackingBodyPool.Put(rtb)
|
||||
}
|
||||
|
||||
var readTrackingBodyPool sync.Pool
|
||||
|
||||
// Read implements io.Reader interface.
|
||||
func (rtb *readTrackingBody) Read(p []byte) (int, error) {
|
||||
if rtb.offset < len(rtb.buf) {
|
||||
if rtb.cannotRetry {
|
||||
return 0, fmt.Errorf("cannot retry reading data from buf")
|
||||
}
|
||||
nb := copy(p, rtb.buf[rtb.offset:])
|
||||
rtb.offset += nb
|
||||
if rtb.bufComplete {
|
||||
if rtb.offset == len(rtb.buf) {
|
||||
return nb, io.EOF
|
||||
}
|
||||
return nb, nil
|
||||
}
|
||||
if nb < len(p) {
|
||||
nr, err := rtb.readFromStream(p[nb:])
|
||||
return nb + nr, err
|
||||
}
|
||||
return nb, nil
|
||||
if len(rtb.readBuf) > 0 {
|
||||
n := copy(p, rtb.readBuf)
|
||||
rtb.readBuf = rtb.readBuf[n:]
|
||||
return n, nil
|
||||
}
|
||||
if rtb.bufComplete {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return rtb.readFromStream(p)
|
||||
}
|
||||
|
||||
func (rtb *readTrackingBody) readFromStream(p []byte) (int, error) {
|
||||
if rtb.r == nil {
|
||||
if rtb.bufComplete {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return 0, fmt.Errorf("cannot read data after closing the reader")
|
||||
}
|
||||
|
||||
n, err := rtb.r.Read(p)
|
||||
if rtb.cannotRetry {
|
||||
return n, err
|
||||
}
|
||||
if rtb.offset+n > maxRequestBodySizeToRetry.IntN() {
|
||||
rtb.cannotRetry = true
|
||||
}
|
||||
if n > 0 {
|
||||
rtb.offset += n
|
||||
rtb.buf = append(rtb.buf, p[:n]...)
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
rtb.bufComplete = true
|
||||
return n, err
|
||||
}
|
||||
|
||||
if len(rtb.buf)+n > rtb.maxBodySize {
|
||||
rtb.cannotRetry = true
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
rtb.buf = append(rtb.buf, p[:n]...)
|
||||
if err == io.EOF {
|
||||
rtb.bufComplete = true
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (rtb *readTrackingBody) canRetry() bool {
|
||||
return !rtb.cannotRetry
|
||||
if rtb.cannotRetry {
|
||||
return false
|
||||
}
|
||||
if rtb.bufComplete {
|
||||
return true
|
||||
}
|
||||
return rtb.r != nil
|
||||
}
|
||||
|
||||
// Close implements io.Closer interface.
|
||||
func (rtb *readTrackingBody) Close() error {
|
||||
rtb.offset = 0
|
||||
if !rtb.cannotRetry {
|
||||
rtb.readBuf = rtb.buf
|
||||
} else {
|
||||
rtb.readBuf = nil
|
||||
}
|
||||
|
||||
// Close rtb.r only if the request body is completely read or if it is too big.
|
||||
// http.Roundtrip performs body.Close call even without any Read calls,
|
||||
@@ -584,38 +611,3 @@ func (rtb *readTrackingBody) Close() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var readTrackingBodyPool sync.Pool
|
||||
|
||||
func getReadTrackingBody(origin io.ReadCloser, b int) *readTrackingBody {
|
||||
bufSize := 1024
|
||||
if b > 0 && b < maxRequestBodySizeToRetry.IntN() {
|
||||
bufSize = b
|
||||
}
|
||||
v := readTrackingBodyPool.Get()
|
||||
if v == nil {
|
||||
v = &readTrackingBody{
|
||||
buf: make([]byte, 0, bufSize),
|
||||
}
|
||||
}
|
||||
rtb := v.(*readTrackingBody)
|
||||
rtb.r = origin
|
||||
if bufSize > cap(rtb.buf) {
|
||||
rtb.buf = make([]byte, 0, bufSize)
|
||||
}
|
||||
|
||||
return rtb
|
||||
}
|
||||
|
||||
func putReadTrackingBody(rtb *readTrackingBody) {
|
||||
if rtb.r != nil {
|
||||
_ = rtb.r.Close()
|
||||
}
|
||||
rtb.r = nil
|
||||
rtb.buf = rtb.buf[:0]
|
||||
rtb.offset = 0
|
||||
rtb.cannotRetry = false
|
||||
rtb.bufComplete = false
|
||||
|
||||
readTrackingBodyPool.Put(rtb)
|
||||
}
|
||||
|
||||
@@ -6,14 +6,15 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadTrackingBodyRetrySuccess(t *testing.T) {
|
||||
f := func(s string) {
|
||||
func TestReadTrackingBody_RetrySuccess(t *testing.T) {
|
||||
f := func(s string, maxBodySize int) {
|
||||
t.Helper()
|
||||
rtb := &readTrackingBody{
|
||||
r: io.NopCloser(bytes.NewBufferString(s)),
|
||||
}
|
||||
|
||||
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
|
||||
defer putReadTrackingBody(rtb)
|
||||
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true")
|
||||
t.Fatalf("canRetry() must return true before reading anything")
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
data, err := io.ReadAll(rtb)
|
||||
@@ -32,41 +33,99 @@ func TestReadTrackingBodyRetrySuccess(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
f("")
|
||||
f("foo")
|
||||
f("foobar")
|
||||
f(newTestString(maxRequestBodySizeToRetry.IntN()))
|
||||
f("", 0)
|
||||
f("", -1)
|
||||
f("", 100)
|
||||
f("foo", 100)
|
||||
f("foobar", 100)
|
||||
f(newTestString(1000), 1000)
|
||||
}
|
||||
|
||||
func TestReadTrackingBodyRetryFailure(t *testing.T) {
|
||||
f := func(s string) {
|
||||
func TestReadTrackingBody_RetrySuccessPartialRead(t *testing.T) {
|
||||
f := func(s string, maxBodySize int) {
|
||||
t.Helper()
|
||||
rtb := &readTrackingBody{
|
||||
r: io.NopCloser(bytes.NewBufferString(s)),
|
||||
|
||||
// Check the case with partial read
|
||||
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
|
||||
defer putReadTrackingBody(rtb)
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
buf := make([]byte, i)
|
||||
n, err := io.ReadFull(rtb, buf)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error when reading %d bytes: %s", i, err)
|
||||
}
|
||||
if n != i {
|
||||
t.Fatalf("unexpected number of bytes read; got %d; want %d", n, i)
|
||||
}
|
||||
if string(buf) != s[:i] {
|
||||
t.Fatalf("unexpected data read with the length %d\ngot\n%s\nwant\n%s", i, buf, s[:i])
|
||||
}
|
||||
if err := rtb.Close(); err != nil {
|
||||
t.Fatalf("unexpected error when closing reader after reading %d bytes", i)
|
||||
}
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true after closing the reader after reading %d bytes", i)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(rtb)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error when reading all the data: %s", err)
|
||||
}
|
||||
if string(data) != s {
|
||||
t.Fatalf("unexpected data read\ngot\n%s\nwant\n%s", data, s)
|
||||
}
|
||||
if err := rtb.Close(); err != nil {
|
||||
t.Fatalf("unexpected error when closing readTrackingBody: %s", err)
|
||||
}
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true")
|
||||
t.Fatalf("canRetry() must return true after closing the reader after reading all the input")
|
||||
}
|
||||
}
|
||||
|
||||
f("", 0)
|
||||
f("", -1)
|
||||
f("", 100)
|
||||
f("foo", 100)
|
||||
f("foobar", 100)
|
||||
f(newTestString(1000), 1000)
|
||||
}
|
||||
|
||||
func TestReadTrackingBody_RetryFailureTooBigBody(t *testing.T) {
|
||||
f := func(s string, maxBodySize int) {
|
||||
t.Helper()
|
||||
|
||||
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
|
||||
defer putReadTrackingBody(rtb)
|
||||
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true before reading anything")
|
||||
}
|
||||
buf := make([]byte, 1)
|
||||
n, err := rtb.Read(buf)
|
||||
n, err := io.ReadFull(rtb, buf)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error when reading a single byte: %s", err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Fatalf("unexpected number of bytes read; got %d; want 1", n)
|
||||
}
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true after reading one byte")
|
||||
}
|
||||
data, err := io.ReadAll(rtb)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error when reading all the data: %s", err)
|
||||
}
|
||||
if string(buf)+string(data) != s {
|
||||
t.Fatalf("unexpected data read\ngot\n%s\nwant\n%s", string(buf)+string(data), s)
|
||||
dataRead := string(buf) + string(data)
|
||||
if dataRead != s {
|
||||
t.Fatalf("unexpected data read\ngot\n%s\nwant\n%s", dataRead, s)
|
||||
}
|
||||
if err := rtb.Close(); err != nil {
|
||||
t.Fatalf("unexpected error when closing readTrackingBody: %s", err)
|
||||
}
|
||||
if rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return false")
|
||||
t.Fatalf("canRetry() must return false after closing the reader")
|
||||
}
|
||||
|
||||
data, err = io.ReadAll(rtb)
|
||||
@@ -78,132 +137,55 @@ func TestReadTrackingBodyRetryFailure(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
f(newTestString(maxRequestBodySizeToRetry.IntN() + 1))
|
||||
f(newTestString(2 * maxRequestBodySizeToRetry.IntN()))
|
||||
const maxBodySize = 1000
|
||||
f(newTestString(maxBodySize+1), maxBodySize)
|
||||
f(newTestString(2*maxBodySize), maxBodySize)
|
||||
}
|
||||
|
||||
// request body not over maxRequestBodySizeToRetry
|
||||
// 1. When writing data downstream, buf only caches part of the data because the downstream connection is disconnected.
|
||||
// 2. retry request: because buf caches some data, first read buf and then read stream when retrying
|
||||
// 3. retry request: the data has been read to buf in the second step. if the request fails, retry to read all buf later.
|
||||
func TestRetryReadSuccessAfterPartialRead(t *testing.T) {
|
||||
f := func(s string) {
|
||||
rtb := &readTrackingBody{
|
||||
r: io.NopCloser(bytes.NewBufferString(s)),
|
||||
buf: make([]byte, 0, len(s)),
|
||||
}
|
||||
func TestReadTrackingBody_RetryFailureZeroOrNegativeMaxBodySize(t *testing.T) {
|
||||
f := func(s string, maxBodySize int) {
|
||||
t.Helper()
|
||||
|
||||
var data []byte
|
||||
var err error
|
||||
halfSize := len(s) / 2
|
||||
if halfSize == 0 {
|
||||
halfSize = 100
|
||||
}
|
||||
buf := make([]byte, halfSize)
|
||||
var n int
|
||||
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
|
||||
defer putReadTrackingBody(rtb)
|
||||
|
||||
// read part of the data
|
||||
n, err = rtb.Read(buf[:])
|
||||
data = append(data, buf[:n]...)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true before reading anything")
|
||||
}
|
||||
data, err := io.ReadAll(rtb)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error when reading all the data: %s", err)
|
||||
}
|
||||
if string(data) != s {
|
||||
t.Fatalf("unexpected data read\ngot\n%s\nwant\n%s", data, s)
|
||||
}
|
||||
|
||||
// request failed when output stream is closed (eg: server connection reset)
|
||||
// would close the reader
|
||||
if err := rtb.Close(); err != nil {
|
||||
t.Fatalf("unexpected error when closing readTrackingBody: %s", err)
|
||||
}
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true")
|
||||
}
|
||||
|
||||
// retry read (read buf + remaining data)
|
||||
data = data[:0]
|
||||
err = nil
|
||||
for err == nil {
|
||||
n, err = rtb.Read(buf[:])
|
||||
data = append(data, buf[:n]...)
|
||||
}
|
||||
if err != io.EOF {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if string(data) != s {
|
||||
t.Fatalf("unexpected data read; got\n%s\nwant\n%s", data, s)
|
||||
}
|
||||
// cannotRetry return false
|
||||
// because the request data is not over maxRequestBodySizeToRetry limit
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true")
|
||||
}
|
||||
}
|
||||
|
||||
f("")
|
||||
f("foo")
|
||||
f("foobar")
|
||||
f(newTestString(maxRequestBodySizeToRetry.IntN()))
|
||||
}
|
||||
|
||||
// request body over maxRequestBodySizeToRetry
|
||||
// 1. When writing data downstream, buf only caches part of the data because the downstream connection is disconnected.
|
||||
// 2. retry request: because buf caches some data, first read buf and then read stream when retrying
|
||||
// 3. retry request: the data has been read to buf in the second step. if the request fails, retry to read all buf later.
|
||||
func TestRetryReadSuccessAfterPartialReadAndCannotRetryAgain(t *testing.T) {
|
||||
f := func(s string) {
|
||||
rtb := &readTrackingBody{
|
||||
r: io.NopCloser(bytes.NewBufferString(s)),
|
||||
buf: make([]byte, 0, len(s)),
|
||||
}
|
||||
|
||||
var data []byte
|
||||
var err error
|
||||
halfSize := len(s) / 2
|
||||
if halfSize == 0 {
|
||||
halfSize = 100
|
||||
}
|
||||
buf := make([]byte, halfSize)
|
||||
var n int
|
||||
|
||||
// read part of the data
|
||||
n, err = rtb.Read(buf[:])
|
||||
data = append(data, buf[:n]...)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
// request failed when output stream is closed (eg: server connection reset)
|
||||
if err := rtb.Close(); err != nil {
|
||||
t.Fatalf("unexpected error when closing readTrackingBody: %s", err)
|
||||
}
|
||||
if !rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return true")
|
||||
}
|
||||
|
||||
// retry read (read buf + remaining data)
|
||||
data = data[:0]
|
||||
err = nil
|
||||
for err == nil {
|
||||
n, err = rtb.Read(buf[:])
|
||||
data = append(data, buf[:n]...)
|
||||
}
|
||||
if err != io.EOF {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if string(data) != s {
|
||||
t.Fatalf("unexpected data read; got\n%s\nwant\n%s", data, s)
|
||||
}
|
||||
|
||||
// cannotRetry returns true
|
||||
// because the request data is over maxRequestBodySizeToRetry limit
|
||||
if rtb.canRetry() {
|
||||
t.Fatalf("canRetry() must return false")
|
||||
t.Fatalf("canRetry() must return false after closing the reader")
|
||||
}
|
||||
data, err = io.ReadAll(rtb)
|
||||
if err == nil {
|
||||
t.Fatalf("expecting non-nil error")
|
||||
}
|
||||
if len(data) != 0 {
|
||||
t.Fatalf("unexpected non-empty data read: %q", data)
|
||||
}
|
||||
}
|
||||
|
||||
f(newTestString(maxRequestBodySizeToRetry.IntN() + 1))
|
||||
f(newTestString(2 * maxRequestBodySizeToRetry.IntN()))
|
||||
f("foobar", 0)
|
||||
f(newTestString(1000), 0)
|
||||
|
||||
f("foobar", -1)
|
||||
f(newTestString(1000), -1)
|
||||
}
|
||||
|
||||
func newTestString(sLen int) string {
|
||||
return string(make([]byte, sLen))
|
||||
data := make([]byte, sLen)
|
||||
for i := range data {
|
||||
data[i] = byte(i)
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
@@ -342,6 +342,55 @@ func TestUserInfoGetBackendURL_SRV(t *testing.T) {
|
||||
f(ui, `/test`, "http://non-exist-dns-addr/test")
|
||||
}
|
||||
|
||||
func TestUserInfoGetBackendURL_SRVZeroBackends(t *testing.T) {
|
||||
f := func(ui *UserInfo, requestURI string) {
|
||||
t.Helper()
|
||||
|
||||
u, err := url.Parse(requestURI)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot parse %q: %s", requestURI, err)
|
||||
}
|
||||
u = normalizeURL(u)
|
||||
up, _ := ui.getURLPrefixAndHeaders(u, nil)
|
||||
if up == nil {
|
||||
t.Fatalf("cannot match available backend: %s", err)
|
||||
}
|
||||
bu := up.getBackendURL()
|
||||
if bu != nil {
|
||||
t.Fatalf("expecting nil backendURL; got %v", bu)
|
||||
}
|
||||
}
|
||||
|
||||
customResolver := &fakeResolver{
|
||||
Resolver: &net.Resolver{},
|
||||
lookupSRVResults: map[string][]*net.SRV{
|
||||
"vmselect": {},
|
||||
},
|
||||
}
|
||||
origResolver := netutil.Resolver
|
||||
netutil.Resolver = customResolver
|
||||
defer func() {
|
||||
netutil.Resolver = origResolver
|
||||
}()
|
||||
|
||||
allowed := true
|
||||
ui := &UserInfo{
|
||||
URLMaps: []URLMap{
|
||||
{
|
||||
SrcPaths: getRegexs([]string{"/select/.+"}),
|
||||
URLPrefix: mustParseURL("http://srv+vmselect"),
|
||||
},
|
||||
},
|
||||
DiscoverBackendIPs: &allowed,
|
||||
URLPrefix: mustParseURL("http://non-exist-dns-addr"),
|
||||
}
|
||||
if err := ui.initURLs(); err != nil {
|
||||
t.Fatalf("cannot initialize urls inside UserInfo: %s", err)
|
||||
}
|
||||
|
||||
f(ui, `/select/0/prometheus/api/v1/query?query=up`)
|
||||
}
|
||||
|
||||
func TestCreateTargetURLFailure(t *testing.T) {
|
||||
f := func(ui *UserInfo, requestURI string) {
|
||||
t.Helper()
|
||||
|
||||
@@ -141,13 +141,7 @@ func (ctx *InsertCtx) ApplyRelabeling() {
|
||||
func (ctx *InsertCtx) FlushBufs() error {
|
||||
sas := sasGlobal.Load()
|
||||
if (sas.IsEnabled() || deduplicator != nil) && !ctx.skipStreamAggr {
|
||||
matchIdxs := matchIdxsPool.Get()
|
||||
matchIdxs.B = ctx.streamAggrCtx.push(ctx.mrs, matchIdxs.B)
|
||||
if !*streamAggrKeepInput {
|
||||
// Remove aggregated rows from ctx.mrs
|
||||
ctx.dropAggregatedRows(matchIdxs.B)
|
||||
}
|
||||
matchIdxsPool.Put(matchIdxs)
|
||||
ctx.streamAggrCtx.push(ctx)
|
||||
}
|
||||
// There is no need in limiting the number of concurrent calls to vmstorage.AddRows() here,
|
||||
// since the number of concurrent FlushBufs() calls should be already limited via writeconcurrencylimiter
|
||||
@@ -166,13 +160,11 @@ func (ctx *InsertCtx) FlushBufs() error {
|
||||
func (ctx *InsertCtx) dropAggregatedRows(matchIdxs []byte) {
|
||||
dst := ctx.mrs[:0]
|
||||
src := ctx.mrs
|
||||
if !*streamAggrDropInput {
|
||||
for idx, match := range matchIdxs {
|
||||
if match == 1 {
|
||||
continue
|
||||
}
|
||||
dst = append(dst, src[idx])
|
||||
for i, match := range matchIdxs {
|
||||
if match == 1 {
|
||||
continue
|
||||
}
|
||||
dst = append(dst, src[i])
|
||||
}
|
||||
tail := src[len(dst):]
|
||||
for i := range tail {
|
||||
@@ -180,5 +172,3 @@ func (ctx *InsertCtx) dropAggregatedRows(matchIdxs []byte) {
|
||||
}
|
||||
ctx.mrs = dst
|
||||
}
|
||||
|
||||
var matchIdxsPool bytesutil.ByteBufferPool
|
||||
|
||||
@@ -62,6 +62,8 @@ func CheckStreamAggrConfig() error {
|
||||
DropInputLabels: *streamAggrDropInputLabels,
|
||||
IgnoreOldSamples: *streamAggrIgnoreOldSamples,
|
||||
IgnoreFirstIntervals: *streamAggrIgnoreFirstIntervals,
|
||||
KeepInput: *streamAggrKeepInput,
|
||||
DropInput: *streamAggrDropInput,
|
||||
}
|
||||
sas, err := streamaggr.LoadFromFile(*streamAggrConfig, pushNoop, opts, "global")
|
||||
if err != nil {
|
||||
@@ -90,6 +92,8 @@ func InitStreamAggr() {
|
||||
DropInputLabels: *streamAggrDropInputLabels,
|
||||
IgnoreOldSamples: *streamAggrIgnoreOldSamples,
|
||||
IgnoreFirstIntervals: *streamAggrIgnoreFirstIntervals,
|
||||
KeepInput: *streamAggrKeepInput,
|
||||
DropInput: *streamAggrDropInput,
|
||||
}
|
||||
sas, err := streamaggr.LoadFromFile(*streamAggrConfig, pushAggregateSeries, opts, "global")
|
||||
if err != nil {
|
||||
@@ -124,6 +128,8 @@ func reloadStreamAggrConfig() {
|
||||
DropInputLabels: *streamAggrDropInputLabels,
|
||||
IgnoreOldSamples: *streamAggrIgnoreOldSamples,
|
||||
IgnoreFirstIntervals: *streamAggrIgnoreFirstIntervals,
|
||||
KeepInput: *streamAggrKeepInput,
|
||||
DropInput: *streamAggrDropInput,
|
||||
}
|
||||
sasNew, err := streamaggr.LoadFromFile(*streamAggrConfig, pushAggregateSeries, opts, "global")
|
||||
if err != nil {
|
||||
@@ -180,12 +186,13 @@ func (ctx *streamAggrCtx) Reset() {
|
||||
ctx.buf = ctx.buf[:0]
|
||||
}
|
||||
|
||||
func (ctx *streamAggrCtx) push(mrs []storage.MetricRow, matchIdxs []byte) []byte {
|
||||
func (ctx *streamAggrCtx) push(insertCtx *InsertCtx) {
|
||||
mn := &ctx.mn
|
||||
tss := ctx.tss
|
||||
labels := ctx.labels
|
||||
samples := ctx.samples
|
||||
buf := ctx.buf
|
||||
mrs := insertCtx.mrs
|
||||
|
||||
tssLen := len(tss)
|
||||
for _, mr := range mrs {
|
||||
@@ -237,18 +244,16 @@ func (ctx *streamAggrCtx) push(mrs []storage.MetricRow, matchIdxs []byte) []byte
|
||||
|
||||
sas := sasGlobal.Load()
|
||||
if sas.IsEnabled() {
|
||||
matchIdxs = sas.Push(tss, matchIdxs)
|
||||
_ = sas.PushWithCallback(tss, func(matchIdxs []byte) {
|
||||
insertCtx.dropAggregatedRows(matchIdxs)
|
||||
})
|
||||
} else if deduplicator != nil {
|
||||
matchIdxs = bytesutil.ResizeNoCopyMayOverallocate(matchIdxs, len(tss))
|
||||
for i := range matchIdxs {
|
||||
matchIdxs[i] = 1
|
||||
}
|
||||
deduplicator.Push(tss)
|
||||
mrs = mrs[:0]
|
||||
}
|
||||
|
||||
ctx.Reset()
|
||||
|
||||
return matchIdxs
|
||||
insertCtx.mrs = mrs
|
||||
}
|
||||
|
||||
func pushAggregateSeries(tss []prompbmarshal.TimeSeries) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/opentelemetry/firehose"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -343,7 +344,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var bb bytesutil.ByteBuffer
|
||||
promscrape.WriteConfigData(&bb)
|
||||
fmt.Fprintf(w, `{"status":"success","data":{"yaml":%q}}`, bb.B)
|
||||
fmt.Fprintf(w, `{"status":"success","data":{"yaml":%s}}`, stringsutil.JSONString(string(bb.B)))
|
||||
return true
|
||||
case "/prometheus/-/reload", "/-/reload":
|
||||
if !httpserver.CheckAuthFlag(w, r, reloadAuthKey) {
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
// ActiveQueriesHandler returns response to /api/v1/status/active_queries
|
||||
@@ -23,8 +25,8 @@ func ActiveQueriesHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
fmt.Fprintf(w, `{"status":"ok","data":[`)
|
||||
for i, aqe := range aqes {
|
||||
d := now.Sub(aqe.startTime)
|
||||
fmt.Fprintf(w, `{"duration":"%.3fs","id":"%016X","remote_addr":%s,"query":%q,"start":%d,"end":%d,"step":%d}`,
|
||||
d.Seconds(), aqe.qid, aqe.quotedRemoteAddr, aqe.q, aqe.start, aqe.end, aqe.step)
|
||||
fmt.Fprintf(w, `{"duration":"%.3fs","id":"%016X","remote_addr":%s,"query":%s,"start":%d,"end":%d,"step":%d}`,
|
||||
d.Seconds(), aqe.qid, aqe.quotedRemoteAddr, stringsutil.JSONString(aqe.q), aqe.start, aqe.end, aqe.step)
|
||||
if i+1 < len(aqes) {
|
||||
fmt.Fprintf(w, `,`)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -74,13 +75,13 @@ func initQueryStats() {
|
||||
}
|
||||
|
||||
func (qst *queryStatsTracker) writeJSONQueryStats(w io.Writer, topN int, maxLifetime time.Duration) {
|
||||
fmt.Fprintf(w, `{"topN":"%d","maxLifetime":%q,`, topN, maxLifetime)
|
||||
fmt.Fprintf(w, `{"topN":"%d","maxLifetime":"%s",`, topN, maxLifetime)
|
||||
fmt.Fprintf(w, `"search.queryStats.lastQueriesCount":%d,`, *lastQueriesCount)
|
||||
fmt.Fprintf(w, `"search.queryStats.minQueryDuration":%q,`, *minQueryDuration)
|
||||
fmt.Fprintf(w, `"search.queryStats.minQueryDuration":"%s",`, *minQueryDuration)
|
||||
fmt.Fprintf(w, `"topByCount":[`)
|
||||
topByCount := qst.getTopByCount(topN, maxLifetime)
|
||||
for i, r := range topByCount {
|
||||
fmt.Fprintf(w, `{"query":%q,"timeRangeSeconds":%d,"count":%d}`, r.query, r.timeRangeSecs, r.count)
|
||||
fmt.Fprintf(w, `{"query":%s,"timeRangeSeconds":%d,"count":%d}`, stringsutil.JSONString(r.query), r.timeRangeSecs, r.count)
|
||||
if i+1 < len(topByCount) {
|
||||
fmt.Fprintf(w, `,`)
|
||||
}
|
||||
@@ -88,7 +89,7 @@ func (qst *queryStatsTracker) writeJSONQueryStats(w io.Writer, topN int, maxLife
|
||||
fmt.Fprintf(w, `],"topByAvgDuration":[`)
|
||||
topByAvgDuration := qst.getTopByAvgDuration(topN, maxLifetime)
|
||||
for i, r := range topByAvgDuration {
|
||||
fmt.Fprintf(w, `{"query":%q,"timeRangeSeconds":%d,"avgDurationSeconds":%.3f,"count":%d}`, r.query, r.timeRangeSecs, r.duration.Seconds(), r.count)
|
||||
fmt.Fprintf(w, `{"query":%s,"timeRangeSeconds":%d,"avgDurationSeconds":%.3f,"count":%d}`, stringsutil.JSONString(r.query), r.timeRangeSecs, r.duration.Seconds(), r.count)
|
||||
if i+1 < len(topByAvgDuration) {
|
||||
fmt.Fprintf(w, `,`)
|
||||
}
|
||||
@@ -96,7 +97,7 @@ func (qst *queryStatsTracker) writeJSONQueryStats(w io.Writer, topN int, maxLife
|
||||
fmt.Fprintf(w, `],"topBySumDuration":[`)
|
||||
topBySumDuration := qst.getTopBySumDuration(topN, maxLifetime)
|
||||
for i, r := range topBySumDuration {
|
||||
fmt.Fprintf(w, `{"query":%q,"timeRangeSeconds":%d,"sumDurationSeconds":%.3f,"count":%d}`, r.query, r.timeRangeSecs, r.duration.Seconds(), r.count)
|
||||
fmt.Fprintf(w, `{"query":%s,"timeRangeSeconds":%d,"sumDurationSeconds":%.3f,"count":%d}`, stringsutil.JSONString(r.query), r.timeRangeSecs, r.duration.Seconds(), r.count)
|
||||
if i+1 < len(topBySumDuration) {
|
||||
fmt.Fprintf(w, `,`)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "./static/css/main.fce049bf.css",
|
||||
"main.js": "./static/js/main.4b213512.js",
|
||||
"main.js": "./static/js/main.ff023df1.js",
|
||||
"static/js/685.bebe1265.chunk.js": "./static/js/685.bebe1265.chunk.js",
|
||||
"static/media/MetricsQL.md": "./static/media/MetricsQL.aaabf95f2c9bf356bde4.md",
|
||||
"static/media/MetricsQL.md": "./static/media/MetricsQL.3de5efa763ef6e05a579.md",
|
||||
"index.html": "./index.html"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.fce049bf.css",
|
||||
"static/js/main.4b213512.js"
|
||||
"static/js/main.ff023df1.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.4b213512.js"></script><link href="./static/css/main.fce049bf.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.ff023df1.js"></script><link href="./static/css/main.fce049bf.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
File diff suppressed because one or more lines are too long
2
app/vmselect/vmui/static/js/main.ff023df1.js
Normal file
2
app/vmselect/vmui/static/js/main.ff023df1.js
Normal file
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @remix-run/router v1.15.1
|
||||
* @remix-run/router v1.17.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router DOM v6.22.1
|
||||
* React Router DOM v6.24.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
@@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router v6.22.1
|
||||
* React Router v6.24.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
@@ -220,9 +220,11 @@ See also [descent_over_time](#descent_over_time).
|
||||
over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [median_over_time](#median_over_time).
|
||||
See also [median_over_time](#median_over_time), [min_over_time](#min_over_time) and [max_over_time](#max_over_time).
|
||||
|
||||
#### changes
|
||||
|
||||
@@ -262,6 +264,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time), [share_eq_over_time](#share_eq_over_time) and [count_values_over_time](#count_values_over_time).
|
||||
|
||||
#### count_gt_over_time
|
||||
@@ -272,6 +276,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time) and [share_gt_over_time](#share_gt_over_time).
|
||||
|
||||
#### count_le_over_time
|
||||
@@ -282,6 +288,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time) and [share_le_over_time](#share_le_over_time).
|
||||
|
||||
#### count_ne_over_time
|
||||
@@ -292,7 +300,9 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
See also [count_over_time](#count_over_time).
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time) and [count_eq_over_time](#count_eq_over_time).
|
||||
|
||||
#### count_over_time
|
||||
|
||||
@@ -313,6 +323,8 @@ The results are calculated independently per each time series returned from the
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_eq_over_time](#count_eq_over_time), [count_values](#count_values) and [distinct_over_time](#distinct_over_time) and [label_match](#label_match).
|
||||
|
||||
#### decreases_over_time
|
||||
@@ -432,6 +444,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### histogram_over_time
|
||||
|
||||
`histogram_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates
|
||||
@@ -443,11 +457,15 @@ For example, the following query calculates median temperature by country over t
|
||||
|
||||
`histogram_quantile(0.5, sum(histogram_over_time(temperature[24h])) by (vmrange,country))`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### hoeffding_bound_lower
|
||||
|
||||
`hoeffding_bound_lower(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates
|
||||
lower [Hoeffding bound](https://en.wikipedia.org/wiki/Hoeffding%27s_inequality) for the given `phi` in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [hoeffding_bound_upper](#hoeffding_bound_upper).
|
||||
|
||||
#### hoeffding_bound_upper
|
||||
@@ -455,6 +473,8 @@ See also [hoeffding_bound_upper](#hoeffding_bound_upper).
|
||||
`hoeffding_bound_upper(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates
|
||||
upper [Hoeffding bound](https://en.wikipedia.org/wiki/Hoeffding%27s_inequality) for the given `phi` in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [hoeffding_bound_lower](#hoeffding_bound_lower).
|
||||
|
||||
#### holt_winters
|
||||
@@ -462,8 +482,9 @@ See also [hoeffding_bound_lower](#hoeffding_bound_lower).
|
||||
`holt_winters(series_selector[d], sf, tf)` is a [rollup function](#rollup-functions), which calculates Holt-Winters value
|
||||
(aka [double exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing#Double_exponential_smoothing)) for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
over the given lookbehind window `d` using the given smoothing factor `sf` and the given trend factor `tf`.
|
||||
Both `sf` and `tf` must be in the range `[0...1]`. It is expected that the [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
|
||||
returns time series of [gauge type](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
Both `sf` and `tf` must be in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
@@ -495,13 +516,14 @@ See also [deriv](#deriv).
|
||||
|
||||
`increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the increase over the given lookbehind window `d`
|
||||
per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
Unlike Prometheus, it takes into account the last sample before the given lookbehind window `d` when calculating the result.
|
||||
See [this article](https://medium.com/@romanhavronenko/victoriametrics-promql-compliance-d4318203f51e) for details.
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [increase_pure](#increase_pure), [increase_prometheus](#increase_prometheus) and [delta](#delta).
|
||||
@@ -510,12 +532,13 @@ See also [increase_pure](#increase_pure), [increase_prometheus](#increase_promet
|
||||
|
||||
`increase_prometheus(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the increase
|
||||
over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
It doesn't take into account the last sample before the given lookbehind window `d` when calculating the result in the same way as Prometheus does.
|
||||
See [this article](https://medium.com/@romanhavronenko/victoriametrics-promql-compliance-d4318203f51e) for details.
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [increase_pure](#increase_pure) and [increase](#increase).
|
||||
|
||||
#### increase_pure
|
||||
@@ -524,6 +547,10 @@ See also [increase_pure](#increase_pure) and [increase](#increase).
|
||||
of the following corner case - it assumes that [counters](https://docs.victoriametrics.com/keyconcepts/#counter) always start from 0,
|
||||
while [increase](#increase) ignores the first value in a series if it is too big.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [increase](#increas) and [increase_prometheus](#increase_prometheus).
|
||||
|
||||
#### increases_over_time
|
||||
|
||||
`increases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
@@ -540,15 +567,18 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### irate
|
||||
|
||||
`irate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the "instant" per-second increase rate over
|
||||
the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [rate](#rate) and [rollup_rate](#rollup_rate).
|
||||
@@ -587,6 +617,8 @@ See also [duration_over_time](#duration_over_time) and [lag](#lag).
|
||||
over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [mad](#mad), [range_mad](#range_mad) and [outlier_iqr_over_time](#outlier_iqr_over_time).
|
||||
|
||||
#### max_over_time
|
||||
@@ -594,9 +626,11 @@ See also [mad](#mad), [range_mad](#range_mad) and [outlier_iqr_over_time](#outli
|
||||
`max_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the maximum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [tmax_over_time](#tmax_over_time).
|
||||
See also [tmax_over_time](#tmax_over_time) and [min_over_time](#min_over_time).
|
||||
|
||||
#### median_over_time
|
||||
|
||||
@@ -604,6 +638,8 @@ See also [tmax_over_time](#tmax_over_time).
|
||||
on the given lookbehind window `d` per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [avg_over_time](#avg_over_time).
|
||||
|
||||
#### min_over_time
|
||||
@@ -611,9 +647,11 @@ See also [avg_over_time](#avg_over_time).
|
||||
`min_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the minimum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [tmin_over_time](#tmin_over_time).
|
||||
See also [tmin_over_time](#tmin_over_time) and [max_over_time](#max_over_time).
|
||||
|
||||
#### mode_over_time
|
||||
|
||||
@@ -622,6 +660,8 @@ for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). It is expected that [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
values are discrete.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### outlier_iqr_over_time
|
||||
|
||||
`outlier_iqr_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last sample on the given lookbehind window `d`
|
||||
@@ -632,6 +672,8 @@ if its value is either smaller than the `q25-1.5*iqr` or bigger than `q75+1.5*iq
|
||||
The `outlier_iqr_over_time()` is useful for detecting anomalies in gauge values based on the previous history of values.
|
||||
For example, `outlier_iqr_over_time(memory_usage_bytes[1h])` triggers when `memory_usage_bytes` suddenly goes outside the usual value range for the last hour.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [outliers_iqr](#outliers_iqr).
|
||||
|
||||
#### predict_linear
|
||||
@@ -659,6 +701,8 @@ This function is supported by PromQL.
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
The `phi` value must be in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [quantiles_over_time](#quantiles_over_time).
|
||||
@@ -670,6 +714,8 @@ over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
The function returns individual series per each `phi*` with `{phiLabel="phi*"}` label. `phi*` values must be in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [quantile_over_time](#quantile_over_time).
|
||||
|
||||
#### range_over_time
|
||||
@@ -680,11 +726,12 @@ E.g. it calculates `max_over_time(series_selector[d]) - min_over_time(series_sel
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### rate
|
||||
|
||||
`rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average per-second increase rate
|
||||
over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
If the lookbehind window is skipped in square brackets, then it is automatically calculated as `max(step, scrape_interval)`, where `step` is the query arg value
|
||||
passed to [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query) or [/api/v1/query](https://docs.victoriametrics.com/keyconcepts/#instant-query),
|
||||
@@ -703,6 +750,8 @@ See also [irate](#irate) and [rollup_rate](#rollup_rate).
|
||||
on the given lookbehind window `d`. The calculations are performed individually per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
#### resets
|
||||
@@ -710,10 +759,11 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
|
||||
`resets(series_selector[d])` is a [rollup function](#rollup-functions), which returns the number
|
||||
of [counter](https://docs.victoriametrics.com/keyconcepts/#counter) resets over the given lookbehind window `d`
|
||||
per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
#### rollup
|
||||
@@ -725,6 +775,10 @@ These values are calculated individually per each time series returned from the
|
||||
Optional 2nd argument `"min"`, `"max"` or `"avg"` can be passed to keep only one calculation result and without adding a label.
|
||||
See also [label_match](#label_match).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [rollup_rate](#rollup_rate).
|
||||
|
||||
#### rollup_candlestick
|
||||
|
||||
`rollup_candlestick(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `open`, `high`, `low` and `close` values (aka OHLC)
|
||||
@@ -736,6 +790,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
Optional 2nd argument `"open"`, `"high"` or `"low"` or `"close"` can be passed to keep only one calculation result and without adding a label.
|
||||
See also [label_match](#label_match).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### rollup_delta
|
||||
|
||||
`rollup_delta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates differences between adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
@@ -762,6 +818,8 @@ See also [label_match](#label_match).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
See also [rollup](#rollup) and [rollup_rate](#rollup_rate).
|
||||
|
||||
#### rollup_increase
|
||||
|
||||
`rollup_increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates increases for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
@@ -774,12 +832,17 @@ See also [label_match](#label_match).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names. See also [rollup_delta](#rollup_delta).
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [rollup](#rollup) and [rollup_rate](#rollup_rate).
|
||||
|
||||
#### rollup_rate
|
||||
|
||||
`rollup_rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second change rates
|
||||
for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated per-second change rates
|
||||
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
|
||||
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
See [this article](https://valyala.medium.com/why-irate-from-prometheus-doesnt-capture-spikes-45f9896d7832) in order to understand better
|
||||
when to use `rollup_rate()`.
|
||||
@@ -787,10 +850,12 @@ when to use `rollup_rate()`.
|
||||
Optional 2nd argument `"min"`, `"max"` or `"avg"` can be passed to keep only one calculation result and without adding a label.
|
||||
See also [label_match](#label_match).
|
||||
|
||||
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [rollup](#rollup) and [rollup_increase](#rollup_increase).
|
||||
|
||||
#### rollup_scrape_interval
|
||||
|
||||
`rollup_scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the interval in seconds between
|
||||
@@ -824,6 +889,8 @@ This function is useful for calculating SLI and SLO. Example: `share_gt_over_tim
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [share_le_over_time](#share_le_over_time) and [count_gt_over_time](#count_gt_over_time).
|
||||
|
||||
#### share_le_over_time
|
||||
@@ -838,6 +905,8 @@ the share of time series values for the last 24 hours when memory usage was belo
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [share_gt_over_time](#share_gt_over_time) and [count_le_over_time](#count_le_over_time).
|
||||
|
||||
#### share_eq_over_time
|
||||
@@ -849,6 +918,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_eq_over_time](#count_eq_over_time).
|
||||
|
||||
#### stale_samples_over_time
|
||||
@@ -866,6 +937,8 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [stdvar_over_time](#stdvar_over_time).
|
||||
@@ -877,6 +950,8 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [stddev_over_time](#stddev_over_time).
|
||||
@@ -888,6 +963,8 @@ values equal to `eq` on the given lookbehind window `d` per each time series ret
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [sum_over_time](#sum_over_time) and [count_eq_over_time](#count_eq_over_time).
|
||||
|
||||
#### sum_gt_over_time
|
||||
@@ -897,6 +974,8 @@ values bigger than `gt` on the given lookbehind window `d` per each time series
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [sum_over_time](#sum_over_time) and [count_gt_over_time](#count_gt_over_time).
|
||||
|
||||
#### sum_le_over_time
|
||||
@@ -906,6 +985,8 @@ values smaller or equal to `le` on the given lookbehind window `d` per each time
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [sum_over_time](#sum_over_time) and [count_le_over_time](#count_le_over_time).
|
||||
|
||||
#### sum_over_time
|
||||
@@ -915,6 +996,8 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
#### sum2_over_time
|
||||
@@ -924,6 +1007,8 @@ values on the given lookbehind window `d` per each time series returned from the
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### timestamp
|
||||
|
||||
`timestamp(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
|
||||
@@ -1001,6 +1086,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [zscore](#zscore), [range_trim_zscore](#range_trim_zscore) and [outlier_iqr_over_time](#outlier_iqr_over_time).
|
||||
|
||||
|
||||
@@ -2230,7 +2317,8 @@ Any [rollup function](#rollup-functions) for something other than [series select
|
||||
Nested rollup functions can be implicit thanks to the [implicit query conversions](#implicit-query-conversions).
|
||||
For example, `delta(sum(m))` is implicitly converted to `delta(sum(default_rollup(m))[1i:1i])`, so it becomes a subquery,
|
||||
since it contains [default_rollup](#default_rollup) nested into [delta](#delta).
|
||||
This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
|
||||
This behavior can be disabled or logged via `-search.disableImplicitConversion` and `-search.logImplicitConversion` command-line flags
|
||||
starting from [`v1.101.0` release](https://docs.victoriametrics.com/changelog/).
|
||||
|
||||
VictoriaMetrics performs subqueries in the following way:
|
||||
|
||||
@@ -2263,5 +2351,6 @@ VictoriaMetrics performs the following implicit conversions for incoming queries
|
||||
For example, `avg_over_time(rate(http_requests_total[5m])[1h])` is automatically converted to `avg_over_time(rate(http_requests_total[5m])[1h:1i])`.
|
||||
* If something other than [series selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
|
||||
is passed to [rollup function](#rollup-functions), then a [subquery](#subqueries) with `1i` lookbehind window and `1i` step is automatically formed.
|
||||
For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
|
||||
This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
|
||||
For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
|
||||
This behavior can be disabled or logged via `-search.disableImplicitConversion` and `-search.logImplicitConversion` command-line flags
|
||||
starting from [`v1.101.0` release](https://docs.victoriametrics.com/changelog/).
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/mergeset"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/querytracer"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/syncwg"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/timeutil"
|
||||
)
|
||||
@@ -153,9 +154,9 @@ func AddRows(mrs []storage.MetricRow) error {
|
||||
}
|
||||
resetResponseCacheIfNeeded(mrs)
|
||||
WG.Add(1)
|
||||
err := Storage.AddRows(mrs, uint8(*precisionBits))
|
||||
Storage.AddRows(mrs, uint8(*precisionBits))
|
||||
WG.Done()
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
var errReadOnly = errors.New("the storage is in read-only mode; check -storage.minFreeDiskSpaceBytes command-line flag value")
|
||||
@@ -308,9 +309,9 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
return true
|
||||
}
|
||||
if prometheusCompatibleResponse {
|
||||
fmt.Fprintf(w, `{"status":"success","data":{"name":%q}}`, snapshotPath)
|
||||
fmt.Fprintf(w, `{"status":"success","data":{"name":%s}}`, stringsutil.JSONString(snapshotPath))
|
||||
} else {
|
||||
fmt.Fprintf(w, `{"status":"ok","snapshot":%q}`, snapshotPath)
|
||||
fmt.Fprintf(w, `{"status":"ok","snapshot":%s}`, stringsutil.JSONString(snapshotPath))
|
||||
}
|
||||
return true
|
||||
case "/list":
|
||||
@@ -636,5 +637,6 @@ func writeStorageMetrics(w io.Writer, strg *storage.Storage) {
|
||||
func jsonResponseError(w http.ResponseWriter, err error) {
|
||||
logger.Errorf("%s", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, `{"status":"error","msg":%q}`, err)
|
||||
errStr := err.Error()
|
||||
fmt.Fprintf(w, `{"status":"error","msg":%s}`, stringsutil.JSONString(errStr))
|
||||
}
|
||||
|
||||
@@ -220,9 +220,11 @@ See also [descent_over_time](#descent_over_time).
|
||||
over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [median_over_time](#median_over_time).
|
||||
See also [median_over_time](#median_over_time), [min_over_time](#min_over_time) and [max_over_time](#max_over_time).
|
||||
|
||||
#### changes
|
||||
|
||||
@@ -262,6 +264,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time), [share_eq_over_time](#share_eq_over_time) and [count_values_over_time](#count_values_over_time).
|
||||
|
||||
#### count_gt_over_time
|
||||
@@ -272,6 +276,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time) and [share_gt_over_time](#share_gt_over_time).
|
||||
|
||||
#### count_le_over_time
|
||||
@@ -282,6 +288,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time) and [share_le_over_time](#share_le_over_time).
|
||||
|
||||
#### count_ne_over_time
|
||||
@@ -292,7 +300,9 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
See also [count_over_time](#count_over_time).
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_over_time](#count_over_time) and [count_eq_over_time](#count_eq_over_time).
|
||||
|
||||
#### count_over_time
|
||||
|
||||
@@ -313,6 +323,8 @@ The results are calculated independently per each time series returned from the
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_eq_over_time](#count_eq_over_time), [count_values](#count_values) and [distinct_over_time](#distinct_over_time) and [label_match](#label_match).
|
||||
|
||||
#### decreases_over_time
|
||||
@@ -432,6 +444,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### histogram_over_time
|
||||
|
||||
`histogram_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates
|
||||
@@ -443,11 +457,15 @@ For example, the following query calculates median temperature by country over t
|
||||
|
||||
`histogram_quantile(0.5, sum(histogram_over_time(temperature[24h])) by (vmrange,country))`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### hoeffding_bound_lower
|
||||
|
||||
`hoeffding_bound_lower(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates
|
||||
lower [Hoeffding bound](https://en.wikipedia.org/wiki/Hoeffding%27s_inequality) for the given `phi` in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [hoeffding_bound_upper](#hoeffding_bound_upper).
|
||||
|
||||
#### hoeffding_bound_upper
|
||||
@@ -455,6 +473,8 @@ See also [hoeffding_bound_upper](#hoeffding_bound_upper).
|
||||
`hoeffding_bound_upper(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates
|
||||
upper [Hoeffding bound](https://en.wikipedia.org/wiki/Hoeffding%27s_inequality) for the given `phi` in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [hoeffding_bound_lower](#hoeffding_bound_lower).
|
||||
|
||||
#### holt_winters
|
||||
@@ -462,8 +482,9 @@ See also [hoeffding_bound_lower](#hoeffding_bound_lower).
|
||||
`holt_winters(series_selector[d], sf, tf)` is a [rollup function](#rollup-functions), which calculates Holt-Winters value
|
||||
(aka [double exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing#Double_exponential_smoothing)) for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
over the given lookbehind window `d` using the given smoothing factor `sf` and the given trend factor `tf`.
|
||||
Both `sf` and `tf` must be in the range `[0...1]`. It is expected that the [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
|
||||
returns time series of [gauge type](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
Both `sf` and `tf` must be in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
@@ -495,13 +516,14 @@ See also [deriv](#deriv).
|
||||
|
||||
`increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the increase over the given lookbehind window `d`
|
||||
per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
Unlike Prometheus, it takes into account the last sample before the given lookbehind window `d` when calculating the result.
|
||||
See [this article](https://medium.com/@romanhavronenko/victoriametrics-promql-compliance-d4318203f51e) for details.
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [increase_pure](#increase_pure), [increase_prometheus](#increase_prometheus) and [delta](#delta).
|
||||
@@ -510,12 +532,13 @@ See also [increase_pure](#increase_pure), [increase_prometheus](#increase_promet
|
||||
|
||||
`increase_prometheus(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the increase
|
||||
over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
It doesn't take into account the last sample before the given lookbehind window `d` when calculating the result in the same way as Prometheus does.
|
||||
See [this article](https://medium.com/@romanhavronenko/victoriametrics-promql-compliance-d4318203f51e) for details.
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [increase_pure](#increase_pure) and [increase](#increase).
|
||||
|
||||
#### increase_pure
|
||||
@@ -524,6 +547,10 @@ See also [increase_pure](#increase_pure) and [increase](#increase).
|
||||
of the following corner case - it assumes that [counters](https://docs.victoriametrics.com/keyconcepts/#counter) always start from 0,
|
||||
while [increase](#increase) ignores the first value in a series if it is too big.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [increase](#increas) and [increase_prometheus](#increase_prometheus).
|
||||
|
||||
#### increases_over_time
|
||||
|
||||
`increases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
@@ -540,15 +567,18 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### irate
|
||||
|
||||
`irate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the "instant" per-second increase rate over
|
||||
the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [rate](#rate) and [rollup_rate](#rollup_rate).
|
||||
@@ -587,6 +617,8 @@ See also [duration_over_time](#duration_over_time) and [lag](#lag).
|
||||
over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [mad](#mad), [range_mad](#range_mad) and [outlier_iqr_over_time](#outlier_iqr_over_time).
|
||||
|
||||
#### max_over_time
|
||||
@@ -594,9 +626,11 @@ See also [mad](#mad), [range_mad](#range_mad) and [outlier_iqr_over_time](#outli
|
||||
`max_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the maximum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [tmax_over_time](#tmax_over_time).
|
||||
See also [tmax_over_time](#tmax_over_time) and [min_over_time](#min_over_time).
|
||||
|
||||
#### median_over_time
|
||||
|
||||
@@ -604,6 +638,8 @@ See also [tmax_over_time](#tmax_over_time).
|
||||
on the given lookbehind window `d` per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [avg_over_time](#avg_over_time).
|
||||
|
||||
#### min_over_time
|
||||
@@ -611,9 +647,11 @@ See also [avg_over_time](#avg_over_time).
|
||||
`min_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the minimum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [tmin_over_time](#tmin_over_time).
|
||||
See also [tmin_over_time](#tmin_over_time) and [max_over_time](#max_over_time).
|
||||
|
||||
#### mode_over_time
|
||||
|
||||
@@ -622,6 +660,8 @@ for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). It is expected that [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
values are discrete.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### outlier_iqr_over_time
|
||||
|
||||
`outlier_iqr_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last sample on the given lookbehind window `d`
|
||||
@@ -632,6 +672,8 @@ if its value is either smaller than the `q25-1.5*iqr` or bigger than `q75+1.5*iq
|
||||
The `outlier_iqr_over_time()` is useful for detecting anomalies in gauge values based on the previous history of values.
|
||||
For example, `outlier_iqr_over_time(memory_usage_bytes[1h])` triggers when `memory_usage_bytes` suddenly goes outside the usual value range for the last hour.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [outliers_iqr](#outliers_iqr).
|
||||
|
||||
#### predict_linear
|
||||
@@ -659,6 +701,8 @@ This function is supported by PromQL.
|
||||
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
The `phi` value must be in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [quantiles_over_time](#quantiles_over_time).
|
||||
@@ -670,6 +714,8 @@ over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
The function returns individual series per each `phi*` with `{phiLabel="phi*"}` label. `phi*` values must be in the range `[0...1]`.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [quantile_over_time](#quantile_over_time).
|
||||
|
||||
#### range_over_time
|
||||
@@ -680,11 +726,12 @@ E.g. it calculates `max_over_time(series_selector[d]) - min_over_time(series_sel
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### rate
|
||||
|
||||
`rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average per-second increase rate
|
||||
over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
If the lookbehind window is skipped in square brackets, then it is automatically calculated as `max(step, scrape_interval)`, where `step` is the query arg value
|
||||
passed to [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query) or [/api/v1/query](https://docs.victoriametrics.com/keyconcepts/#instant-query),
|
||||
@@ -703,6 +750,8 @@ See also [irate](#irate) and [rollup_rate](#rollup_rate).
|
||||
on the given lookbehind window `d`. The calculations are performed individually per each time series returned
|
||||
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
#### resets
|
||||
@@ -710,10 +759,11 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
|
||||
`resets(series_selector[d])` is a [rollup function](#rollup-functions), which returns the number
|
||||
of [counter](https://docs.victoriametrics.com/keyconcepts/#counter) resets over the given lookbehind window `d`
|
||||
per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
#### rollup
|
||||
@@ -725,6 +775,10 @@ These values are calculated individually per each time series returned from the
|
||||
Optional 2nd argument `"min"`, `"max"` or `"avg"` can be passed to keep only one calculation result and without adding a label.
|
||||
See also [label_match](#label_match).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [rollup_rate](#rollup_rate).
|
||||
|
||||
#### rollup_candlestick
|
||||
|
||||
`rollup_candlestick(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `open`, `high`, `low` and `close` values (aka OHLC)
|
||||
@@ -736,6 +790,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
Optional 2nd argument `"open"`, `"high"` or `"low"` or `"close"` can be passed to keep only one calculation result and without adding a label.
|
||||
See also [label_match](#label_match).
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### rollup_delta
|
||||
|
||||
`rollup_delta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates differences between adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
@@ -762,6 +818,8 @@ See also [label_match](#label_match).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
See also [rollup](#rollup) and [rollup_rate](#rollup_rate).
|
||||
|
||||
#### rollup_increase
|
||||
|
||||
`rollup_increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates increases for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
@@ -774,12 +832,17 @@ See also [label_match](#label_match).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names. See also [rollup_delta](#rollup_delta).
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [rollup](#rollup) and [rollup_rate](#rollup_rate).
|
||||
|
||||
#### rollup_rate
|
||||
|
||||
`rollup_rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second change rates
|
||||
for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated per-second change rates
|
||||
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
|
||||
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
See [this article](https://valyala.medium.com/why-irate-from-prometheus-doesnt-capture-spikes-45f9896d7832) in order to understand better
|
||||
when to use `rollup_rate()`.
|
||||
@@ -787,10 +850,12 @@ when to use `rollup_rate()`.
|
||||
Optional 2nd argument `"min"`, `"max"` or `"avg"` can be passed to keep only one calculation result and without adding a label.
|
||||
See also [label_match](#label_match).
|
||||
|
||||
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [counters](https://docs.victoriametrics.com/keyconcepts/#counter).
|
||||
|
||||
See also [rollup](#rollup) and [rollup_increase](#rollup_increase).
|
||||
|
||||
#### rollup_scrape_interval
|
||||
|
||||
`rollup_scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the interval in seconds between
|
||||
@@ -824,6 +889,8 @@ This function is useful for calculating SLI and SLO. Example: `share_gt_over_tim
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [share_le_over_time](#share_le_over_time) and [count_gt_over_time](#count_gt_over_time).
|
||||
|
||||
#### share_le_over_time
|
||||
@@ -838,6 +905,8 @@ the share of time series values for the last 24 hours when memory usage was belo
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [share_gt_over_time](#share_gt_over_time) and [count_le_over_time](#count_le_over_time).
|
||||
|
||||
#### share_eq_over_time
|
||||
@@ -849,6 +918,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [count_eq_over_time](#count_eq_over_time).
|
||||
|
||||
#### stale_samples_over_time
|
||||
@@ -866,6 +937,8 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [stdvar_over_time](#stdvar_over_time).
|
||||
@@ -877,6 +950,8 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
See also [stddev_over_time](#stddev_over_time).
|
||||
@@ -888,6 +963,8 @@ values equal to `eq` on the given lookbehind window `d` per each time series ret
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [sum_over_time](#sum_over_time) and [count_eq_over_time](#count_eq_over_time).
|
||||
|
||||
#### sum_gt_over_time
|
||||
@@ -897,6 +974,8 @@ values bigger than `gt` on the given lookbehind window `d` per each time series
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [sum_over_time](#sum_over_time) and [count_gt_over_time](#count_gt_over_time).
|
||||
|
||||
#### sum_le_over_time
|
||||
@@ -906,6 +985,8 @@ values smaller or equal to `le` on the given lookbehind window `d` per each time
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [sum_over_time](#sum_over_time) and [count_le_over_time](#count_le_over_time).
|
||||
|
||||
#### sum_over_time
|
||||
@@ -915,6 +996,8 @@ on the given lookbehind window `d` per each time series returned from the given
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
This function is supported by PromQL.
|
||||
|
||||
#### sum2_over_time
|
||||
@@ -924,6 +1007,8 @@ values on the given lookbehind window `d` per each time series returned from the
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
#### timestamp
|
||||
|
||||
`timestamp(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
|
||||
@@ -1001,6 +1086,8 @@ from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#f
|
||||
|
||||
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
|
||||
|
||||
This function is usually applied to [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
|
||||
|
||||
See also [zscore](#zscore), [range_trim_zscore](#range_trim_zscore) and [outlier_iqr_over_time](#outlier_iqr_over_time).
|
||||
|
||||
|
||||
@@ -2230,7 +2317,8 @@ Any [rollup function](#rollup-functions) for something other than [series select
|
||||
Nested rollup functions can be implicit thanks to the [implicit query conversions](#implicit-query-conversions).
|
||||
For example, `delta(sum(m))` is implicitly converted to `delta(sum(default_rollup(m))[1i:1i])`, so it becomes a subquery,
|
||||
since it contains [default_rollup](#default_rollup) nested into [delta](#delta).
|
||||
This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
|
||||
This behavior can be disabled or logged via `-search.disableImplicitConversion` and `-search.logImplicitConversion` command-line flags
|
||||
starting from [`v1.101.0` release](https://docs.victoriametrics.com/changelog/).
|
||||
|
||||
VictoriaMetrics performs subqueries in the following way:
|
||||
|
||||
@@ -2263,5 +2351,6 @@ VictoriaMetrics performs the following implicit conversions for incoming queries
|
||||
For example, `avg_over_time(rate(http_requests_total[5m])[1h])` is automatically converted to `avg_over_time(rate(http_requests_total[5m])[1h:1i])`.
|
||||
* If something other than [series selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
|
||||
is passed to [rollup function](#rollup-functions), then a [subquery](#subqueries) with `1i` lookbehind window and `1i` step is automatically formed.
|
||||
For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
|
||||
This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
|
||||
For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
|
||||
This behavior can be disabled or logged via `-search.disableImplicitConversion` and `-search.logImplicitConversion` command-line flags
|
||||
starting from [`v1.101.0` release](https://docs.victoriametrics.com/changelog/).
|
||||
|
||||
@@ -48,9 +48,9 @@ const ExploreLogs: FC = () => {
|
||||
|
||||
const newPeriod = getPeriod();
|
||||
setPeriod(newPeriod);
|
||||
fetchLogs(newPeriod);
|
||||
fetchLogHits(newPeriod);
|
||||
|
||||
fetchLogs(newPeriod).then((isSuccess) => {
|
||||
isSuccess && fetchLogHits(newPeriod);
|
||||
}).catch(e => e);
|
||||
setSearchParamsFromKeys( {
|
||||
query,
|
||||
"g0.range_input": duration,
|
||||
@@ -90,7 +90,7 @@ const ExploreLogs: FC = () => {
|
||||
onRun={handleRunQuery}
|
||||
onChangeMarkdownParsing={handleChangeMarkdownParsing}
|
||||
/>
|
||||
{isLoading && <Spinner />}
|
||||
{isLoading && <Spinner message={"Loading logs..."}/>}
|
||||
{error && <Alert variant="error">{error}</Alert>}
|
||||
{!error && (
|
||||
<ExploreLogsBarChart
|
||||
|
||||
@@ -57,7 +57,10 @@ const ExploreLogsBarChart: FC<Props> = ({ logHits, period, error, isLoading }) =
|
||||
"vm-block_mobile": isMobile,
|
||||
})}
|
||||
>
|
||||
{isLoading && <Spinner containerStyles={{ position: "absolute" }}/>}
|
||||
{isLoading && <Spinner
|
||||
message={"Loading hits stats..."}
|
||||
containerStyles={{ position: "absolute" }}
|
||||
/>}
|
||||
{!error && noDataMessage && (
|
||||
<div className="vm-explore-logs-chart__empty">
|
||||
<Alert variant="info">{noDataMessage}</Alert>
|
||||
|
||||
@@ -52,20 +52,23 @@ export const useFetchLogs = (server: string, query: string, limit: number) => {
|
||||
setError(text);
|
||||
setLogs([]);
|
||||
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const lines = text.split("\n").filter(line => line).slice(0, limit);
|
||||
const data = lines.map(parseLineToJSON).filter(line => line) as Logs[];
|
||||
setLogs(data);
|
||||
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||
return true;
|
||||
} catch (e) {
|
||||
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||
if (e instanceof Error && e.name !== "AbortError") {
|
||||
setError(String(e));
|
||||
console.error(e);
|
||||
setLogs([]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||
}, [url, query, limit]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,7 +4,7 @@ services:
|
||||
# And forward them to --remoteWrite.url
|
||||
vmagent:
|
||||
container_name: vmagent
|
||||
image: victoriametrics/vmagent:v1.101.0
|
||||
image: victoriametrics/vmagent:v1.102.0
|
||||
depends_on:
|
||||
- "vminsert"
|
||||
ports:
|
||||
@@ -39,7 +39,7 @@ services:
|
||||
# where N is number of vmstorages (2 in this case).
|
||||
vmstorage-1:
|
||||
container_name: vmstorage-1
|
||||
image: victoriametrics/vmstorage:v1.101.0-cluster
|
||||
image: victoriametrics/vmstorage:v1.102.0-cluster
|
||||
ports:
|
||||
- 8482
|
||||
- 8400
|
||||
@@ -51,7 +51,7 @@ services:
|
||||
restart: always
|
||||
vmstorage-2:
|
||||
container_name: vmstorage-2
|
||||
image: victoriametrics/vmstorage:v1.101.0-cluster
|
||||
image: victoriametrics/vmstorage:v1.102.0-cluster
|
||||
ports:
|
||||
- 8482
|
||||
- 8400
|
||||
@@ -66,7 +66,7 @@ services:
|
||||
# pre-process them and distributes across configured vmstorage shards.
|
||||
vminsert:
|
||||
container_name: vminsert
|
||||
image: victoriametrics/vminsert:v1.101.0-cluster
|
||||
image: victoriametrics/vminsert:v1.102.0-cluster
|
||||
depends_on:
|
||||
- "vmstorage-1"
|
||||
- "vmstorage-2"
|
||||
@@ -81,7 +81,7 @@ services:
|
||||
# vmselect collects results from configured `--storageNode` shards.
|
||||
vmselect-1:
|
||||
container_name: vmselect-1
|
||||
image: victoriametrics/vmselect:v1.101.0-cluster
|
||||
image: victoriametrics/vmselect:v1.102.0-cluster
|
||||
depends_on:
|
||||
- "vmstorage-1"
|
||||
- "vmstorage-2"
|
||||
@@ -94,7 +94,7 @@ services:
|
||||
restart: always
|
||||
vmselect-2:
|
||||
container_name: vmselect-2
|
||||
image: victoriametrics/vmselect:v1.101.0-cluster
|
||||
image: victoriametrics/vmselect:v1.102.0-cluster
|
||||
depends_on:
|
||||
- "vmstorage-1"
|
||||
- "vmstorage-2"
|
||||
@@ -112,7 +112,7 @@ services:
|
||||
# It can be used as an authentication proxy.
|
||||
vmauth:
|
||||
container_name: vmauth
|
||||
image: victoriametrics/vmauth:v1.101.0
|
||||
image: victoriametrics/vmauth:v1.102.0
|
||||
depends_on:
|
||||
- "vmselect-1"
|
||||
- "vmselect-2"
|
||||
@@ -127,7 +127,7 @@ services:
|
||||
# vmalert executes alerting and recording rules
|
||||
vmalert:
|
||||
container_name: vmalert
|
||||
image: victoriametrics/vmalert:v1.101.0
|
||||
image: victoriametrics/vmalert:v1.102.0
|
||||
depends_on:
|
||||
- "vmauth"
|
||||
ports:
|
||||
|
||||
@@ -55,7 +55,7 @@ services:
|
||||
# scraping, storing metrics and serve read requests.
|
||||
victoriametrics:
|
||||
container_name: victoriametrics
|
||||
image: victoriametrics/victoria-metrics:v1.101.0
|
||||
image: victoriametrics/victoria-metrics:v1.102.0
|
||||
ports:
|
||||
- 8428:8428
|
||||
volumes:
|
||||
|
||||
@@ -4,7 +4,7 @@ services:
|
||||
# And forward them to --remoteWrite.url
|
||||
vmagent:
|
||||
container_name: vmagent
|
||||
image: victoriametrics/vmagent:v1.101.0
|
||||
image: victoriametrics/vmagent:v1.102.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
@@ -22,7 +22,7 @@ services:
|
||||
# storing metrics and serve read requests.
|
||||
victoriametrics:
|
||||
container_name: victoriametrics
|
||||
image: victoriametrics/victoria-metrics:v1.101.0
|
||||
image: victoriametrics/victoria-metrics:v1.102.0
|
||||
ports:
|
||||
- 8428:8428
|
||||
- 8089:8089
|
||||
@@ -65,7 +65,7 @@ services:
|
||||
# vmalert executes alerting and recording rules
|
||||
vmalert:
|
||||
container_name: vmalert
|
||||
image: victoriametrics/vmalert:v1.101.0
|
||||
image: victoriametrics/vmalert:v1.102.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
- "alertmanager"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
services:
|
||||
vmagent:
|
||||
container_name: vmagent
|
||||
image: victoriametrics/vmagent:v1.101.0
|
||||
image: victoriametrics/vmagent:v1.102.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
|
||||
victoriametrics:
|
||||
container_name: victoriametrics
|
||||
image: victoriametrics/victoria-metrics:v1.101.0
|
||||
image: victoriametrics/victoria-metrics:v1.102.0
|
||||
ports:
|
||||
- 8428:8428
|
||||
volumes:
|
||||
@@ -51,7 +51,7 @@ services:
|
||||
|
||||
vmalert:
|
||||
container_name: vmalert
|
||||
image: victoriametrics/vmalert:v1.101.0
|
||||
image: victoriametrics/vmalert:v1.102.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
|
||||
@@ -46,7 +46,7 @@ services:
|
||||
- '--config=/config.yml'
|
||||
|
||||
vmsingle:
|
||||
image: victoriametrics/victoria-metrics:v1.101.0
|
||||
image: victoriametrics/victoria-metrics:v1.102.0
|
||||
ports:
|
||||
- '8428:8428'
|
||||
command:
|
||||
|
||||
@@ -19,8 +19,8 @@ On the server:
|
||||
* VictoriaMetrics is running on ports: 8428, 8089, 4242, 2003 and they are bound to the local interface.
|
||||
|
||||
********************************************************************************
|
||||
# This image includes v1.101.0 release of VictoriaMetrics.
|
||||
# See Release notes https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0
|
||||
# This image includes v1.102.0 release of VictoriaMetrics.
|
||||
# See Release notes https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.0
|
||||
|
||||
# Welcome to VictoriaMetrics droplet!
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@ The following `tip` changes can be tested by building VictoriaMetrics components
|
||||
* [How to build vmagent](https://docs.victoriametrics.com/vmagent/#how-to-build-from-sources)
|
||||
* [How to build vmalert](https://docs.victoriametrics.com/vmalert/#how-to-build-from-sources)
|
||||
* [How to build vmauth](https://docs.victoriametrics.com/vmauth/#how-to-build-from-sources)
|
||||
* [How to build vmbackup](https://docs.victoriametrics.com/vmbackup/#how-to-build-from-sources)
|
||||
* [How to build vmrestore](https://docs.victoriametrics.com/vmrestore/#how-to-build-from-sources)
|
||||
* [How to build vmctl](https://docs.victoriametrics.com/vmctl/#how-to-build)
|
||||
* [How to build vmbackup](https://docs.victoriametrics.com/vmbackup/index.html#how-to-build-from-sources)
|
||||
|
||||
Metrics of the latest version of VictoriaMetrics cluster are available for viewing at our
|
||||
[sandbox](https://play-grafana.victoriametrics.com/d/oS7Bi_0Wz_vm/victoriametrics-cluster-vm).
|
||||
@@ -30,6 +31,11 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
|
||||
|
||||
## tip
|
||||
|
||||
|
||||
## [v1.102.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.0)
|
||||
|
||||
Released at 2024-07-17
|
||||
|
||||
**Update note 1: support for snap packages was removed due to lack of interest from community. See this [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6543) for details. Please read about supported package types [here](https://docs.victoriametrics.com/#install).**
|
||||
|
||||
**Update note 2: [stream aggregation config](https://docs.victoriametrics.com/stream-aggregation/#stream-aggregation-config) now prevents setting multiple identical outputs. For example, `outputs: [total, total]` will fail the validation phase. In addition, `outputs: ["quantiles(0.5)", "quantiles(0.9)"]` will fail the validation as well - use `outputs: ["quantiles(0.5, 0.9)"]` instead.**
|
||||
@@ -37,12 +43,6 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
|
||||
* SECURITY: upgrade Go builder from Go1.22.4 to Go1.22.5. See the list of issues addressed in [Go1.22.5](https://github.com/golang/go/issues?q=milestone%3AGo1.22.5+label%3ACherryPickApproved).
|
||||
* SECURITY: upgrade base docker image (Alpine) from 3.20.0 to 3.20.1. See [alpine 3.20.1 release notes](https://www.alpinelinux.org/posts/Alpine-3.20.1-released.html).
|
||||
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): allow overriding `Host` header with backend host before sending the request to the configured backend. See [these docs](https://docs.victoriametrics.com/vmauth/#modifying-http-headers) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6453)
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): reduces CPU usage by reusing request body buffer. Allows to disable requests caching with `-maxRequestBodySizeToRetry=0`. See this [PR](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6533) for details.
|
||||
* FEATURE: [dashboards](https://grafana.com/orgs/victoriametrics): add [Grafana dashboard](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards/vmauth.json) and [alerting rules](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/alerts-vmauth.yml) for [vmauth](https://docs.victoriametrics.com/vmauth/) dashboard. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4313) for details.
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): reduces CPU usage by reusing request body buffer. Allows to disable requests caching with `-maxRequestBodySizeToRetry=0`. See this [PR](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6533) for details.
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/): [`yandexcloud_sd_configs`](https://docs.victoriametrics.com/sd_configs/#yandexcloud_sd_configs): add support for obtaining IAM token in [GCE format](https://yandex.cloud/en-ru/docs/compute/operations/vm-connect/auth-inside-vm#auth-inside-vm) additionally to the [deprecated Amazon EC2 IMDSv1 format](https://yandex.cloud/en/docs/security/standard/authentication#aws-token). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5513).
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/) and [Single-node VictoriaMetrics](https://docs.victoriametrics.com/): add `-graphite.sanitizeMetricName` cmd-line flag for sanitizing metrics ingested via [Graphite protocol](https://docs.victoriametrics.com/#how-to-send-data-from-graphite-compatible-agents-such-as-statsd). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6077).
|
||||
* FEATURE: [streaming aggregation](https://docs.victoriametrics.com/stream-aggregation/): expose the following metrics at `/metrics` page of [vmagent](https://docs.victoriametrics.com/vmagent/) and [single-node VictoriaMetrics](https://docs.victoriametrics.com/):
|
||||
* `vm_streamaggr_matched_samples_total` - the number of input samples matched by the corresponding aggregation rule
|
||||
* `vm_streamaggr_output_samples_total` - the number of output samples produced by the corresponding aggregation rule
|
||||
@@ -52,23 +52,27 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
|
||||
* `url` - `-remoteWrite.url` for the corresponding `-remoteWrite.streamAggr.config`
|
||||
* `path` - path to the corresponding streaming aggregation config file
|
||||
* `position` - the position of the aggregation rule in the corresponding streaming aggregation config file
|
||||
* FEATURE: [vmagent dashboard](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards/vmagent.json): `stream aggregation` section: add graphs based on newly exposed streaming aggregation metrics.
|
||||
* FEATURE: [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): do not retry RPC calls to vmstorage nodes if [complexity limits](https://docs.victoriametrics.com/#resource-usage-limits) were exceeded.
|
||||
* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert/): make `-replay.timeTo` optional in [replay mode](https://docs.victoriametrics.com/vmalert/#rules-backfilling). When omitted, the current timestamp will be used. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6492).
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): show compacted result in the JSON tab for query results. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6559).
|
||||
* FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup/index.html): add support of using Azure Managed Identity and default credentials lookup when performing backups. See configuration docs [here](https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5984) for the details. Thanks to @justinrush for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6518).
|
||||
* FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup/index.html): allow overriding Azure storage domain when performing backups. See configuration docs [here](https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5984) for the details. Thanks to @justinrush for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6518).
|
||||
* FEATURE: [streaming aggregation](https://docs.victoriametrics.com/stream-aggregation/): prevent having duplicated aggregation function as `outputs` in one [aggregation config](https://docs.victoriametrics.com/stream-aggregation/#stream-aggregation-config). It also prevents using `outputs: ["quantiles(0.5)", "quantiles(0.9)"]` instead of `outputs: ["quantiles(0.5, 0.9)"]`, as the former has higher computation cost for producing the same result.
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/) and [Single-node VictoriaMetrics](https://docs.victoriametrics.com/): add `-graphite.sanitizeMetricName` command-line flag for sanitizing metrics ingested via [Graphite protocol](https://docs.victoriametrics.com/#how-to-send-data-from-graphite-compatible-agents-such-as-statsd). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6077).
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/): [`yandexcloud_sd_configs`](https://docs.victoriametrics.com/sd_configs/#yandexcloud_sd_configs): add support for obtaining IAM token in [GCE format](https://yandex.cloud/en-ru/docs/compute/operations/vm-connect/auth-inside-vm#auth-inside-vm) additionally to the [deprecated Amazon EC2 IMDSv1 format](https://yandex.cloud/en/docs/security/standard/authentication#aws-token). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5513).
|
||||
* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert/): make `-replay.timeTo` optional in [replay mode](https://docs.victoriametrics.com/vmalert/#rules-backfilling). When omitted, the current timestamp will be used. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6492).
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): reduce CPU usage when proxying data ingestion requests.
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): allow disabling request body caching with `-maxRequestBodySizeToRetry=0`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6445). Thanks to @shichanglin5 for [the pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6533).
|
||||
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): allow overriding `Host` header with backend host before sending the request to the configured backend. See [these docs](https://docs.victoriametrics.com/vmauth/#modifying-http-headers) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6453).
|
||||
* FEATURE: [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): do not retry RPC calls to vmstorage nodes if [complexity limits](https://docs.victoriametrics.com/#resource-usage-limits) were exceeded.
|
||||
* FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup/) and [vmrestore](https://docs.victoriametrics.com/vmrestore/): add support for [Azure Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) and default credentials lookup. See [these docs](https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5984) for the details. Thanks to @justinrush for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6518).
|
||||
* FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup/) and [vmrestore](https://docs.victoriametrics.com/vmbackup/): allow overriding Azure storage domain when performing backups via `AZURE_STORAGE_DOMAIN` environment variable. See [these docs](https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5984). Thanks to @justinrush for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6518).
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): show compacted result in the JSON tab for query results. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6559).
|
||||
* FEATURE: [dashboards](https://grafana.com/orgs/victoriametrics): add [Grafana dashboard](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards/vmauth.json) and [alerting rules](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/alerts-vmauth.yml) for [vmauth](https://docs.victoriametrics.com/vmauth/) dashboard. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4313) for details.
|
||||
* FEATURE: [vmagent dashboard](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards/vmagent.json): `stream aggregation` section: add graphs based on newly exposed streaming aggregation metrics.
|
||||
|
||||
* BUGFIX: [vmgateway](https://docs.victoriametrics.com/vmgateway/): properly apply read and write based rate limits. See this [issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6148) for details.
|
||||
* BUGFIX: [docker-compose](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker#docker-compose-environment-for-victoriametrics): fix incorrect link to vmui from [VictoriaMetrics plugin in Grafana](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker#grafana).
|
||||
* BUGFIX: [docker-compose](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker#docker-compose-environment-for-victoriametrics): fix incorrect link to vmui from [VictoriaMetrics plugin in Grafana](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker#grafana).
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): Fix the dateMetricIDCache consistency issue that leads to duplicate per-day index entries when new time series are inserted concurrently. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6534) for details.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix incorrect redirection in WebUI of vmalert. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6603) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6620).
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix input cursor position reset in modal settings. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6530).
|
||||
* BUGFIX: [vmbackupmanager](https://docs.victoriametrics.com/vmbackupmanager/): fix `vm_backup_last_run_failed` metric not being properly initialized during startup. Previously, it could imply an error even if the backup have been completed successfully. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6550) for the details.
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly calculate [histogram_quantile](https://docs.victoriametrics.com/MetricsQL.html#histogram_quantile) over Prometheus buckets with inconsistent values. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4580#issuecomment-2186659102) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6547). Updates [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2819).
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/metricsql/): properly calculate [histogram_quantile](https://docs.victoriametrics.com/metricsql/#histogram_quantile) over Prometheus buckets with inconsistent values. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4580#issuecomment-2186659102) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6547). Updates [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2819).
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent/): fix panic when using multiple topics with the same name when [ingesting metrics from Kafka](https://docs.victoriametrics.com/vmagent/#kafka-integration). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6636) for the details.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix incorrect redirection in WebUI of vmalert. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6603) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6620).
|
||||
* BUGFIX: [vmgateway](https://docs.victoriametrics.com/vmgateway/): properly apply read and write based rate limits. See this [issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6148) for details.
|
||||
* BUGFIX: [vmbackupmanager](https://docs.victoriametrics.com/vmbackupmanager/): fix `vm_backup_last_run_failed` metric not being properly initialized during startup. Previously, it could imply an error even if the backup have been completed successfully. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6550) for the details.
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix input cursor position reset in modal settings. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6530).
|
||||
* BUGFIX: [docker-compose](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker#docker-compose-environment-for-victoriametrics): fix incorrect link to vmui from [VictoriaMetrics plugin in Grafana](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker#grafana).
|
||||
|
||||
## [v1.102.0-rc2](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.0-rc2)
|
||||
|
||||
@@ -333,6 +337,30 @@ Released at 2024-02-14
|
||||
* BUGFIX: [dashboards](https://grafana.com/orgs/victoriametrics): update `Storage full ETA` panels for Single-node and Cluster dashboards to prevent them from showing negative or blank results caused by increase of deduplicated samples. Deduplicated samples were part of the expression to provide a better estimate for disk usage, but due to sporadic nature of [deduplication](https://docs.victoriametrics.com/#deduplication) in VictoriaMetrics it rather produced skewed results. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/5747).
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/#vmalert): reduce memory usage for ENT version of vmalert for configurations with high number of groups with enabled multitenancy.
|
||||
|
||||
## [v1.97.6](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.6)
|
||||
|
||||
Released at 2024-07-17
|
||||
|
||||
**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**
|
||||
|
||||
* SECURITY: upgrade Go builder from Go1.22.4 to Go1.22.5. See the list of issues addressed in [Go1.22.5](https://github.com/golang/go/issues?q=milestone%3AGo1.22.5+label%3ACherryPickApproved).
|
||||
* SECURITY: upgrade base docker image (Alpine) from 3.20.0 to 3.20.1. See [alpine 3.20.1 release notes](https://www.alpinelinux.org/posts/Alpine-3.20.1-released.html).
|
||||
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent/): fix panic when using multiple topics with the same name when [ingesting metrics from Kafka](https://docs.victoriametrics.com/vmagent/#kafka-integration). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6636) for the details.
|
||||
* BUGFIX: all VictoriaMetrics components: properly calculate `process_resident_memory_bytes` metric for OS with non-default value of memory page size. See this [issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6457) for details.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix path for system links printed on default vmalert's UI page when `-http.pathPrefix` is set.
|
||||
* BUGFIX: [vmbackup](https://docs.victoriametrics.com/vmbackup/): properly configure authentication with S3 when `-configFilePath` cmd-line flag is specified.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/) enterprise: properly configure authentication with S3 when `-s3.configFilePath` cmd-line flag is specified for reading rule configs.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): properly specify oauth2 `ClientSecret` when configuring authentication for `notifier.url`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6471) for details. Thanks to @yincongcyincong for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6478).
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix incorrect redirection in WebUI of vmalert. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6603) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6620).
|
||||
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): add validation for the max value specified for `-retentionPeriod`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6330) for details.
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): **copy row** button in Table view produces unexpected result. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6421) and [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6495).
|
||||
* BUGFIX: [vmalert-tool](https://docs.victoriametrics.com/vmalert-tool/): prevent hanging when processing groups without rules. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6500).
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix input cursor position reset in modal settings. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6530).
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/metricsql/): properly calculate [histogram_quantile](https://docs.victoriametrics.com/metricsql/#histogram_quantile) over Prometheus buckets with inconsistent values. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4580#issuecomment-2186659102) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6547). Updates [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2819).
|
||||
|
||||
## [v1.97.5](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.5)
|
||||
|
||||
Released at 2024-06-07
|
||||
@@ -524,6 +552,24 @@ See changes [here](https://docs.victoriametrics.com/changelog_2023/#v1950)
|
||||
|
||||
See changes [here](https://docs.victoriametrics.com/changelog_2023/#v1940)
|
||||
|
||||
## [v1.93.16](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.93.16)
|
||||
|
||||
Released at 2024-07-17
|
||||
|
||||
**v1.93.x is a line of [LTS releases](https://docs.victoriametrics.com/lts-releases/). It contains important up-to-date bugfixes.
|
||||
The v1.93.x line will be supported for at least 12 months since [v1.93.0](https://docs.victoriametrics.com/CHANGELOG.html#v1930) release**
|
||||
|
||||
* SECURITY: upgrade Go builder from Go1.22.4 to Go1.22.5. See the list of issues addressed in [Go1.22.5](https://github.com/golang/go/issues?q=milestone%3AGo1.22.5+label%3ACherryPickApproved).
|
||||
* SECURITY: upgrade base docker image (Alpine) from 3.20.0 to 3.20.1. See [alpine 3.20.1 release notes](https://www.alpinelinux.org/posts/Alpine-3.20.1-released.html).
|
||||
|
||||
* BUGFIX: [vmbackup](https://docs.victoriametrics.com/vmbackup/): properly configure authentication with S3 when `-configFilePath` cmd-line flag is specified.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix path for system links printed on default vmalert's UI page when `-http.pathPrefix` is set.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix incorrect redirection in WebUI of vmalert. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6603) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6620).
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/) enterprise: properly configure authentication with S3 when `-s3.configFilePath` cmd-line flag is specified for reading rule configs.
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): properly specify oauth2 `ClientSecret` when configuring authentication for `notifier.url`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6471) for details. Thanks to @yincongcyincong for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6478).
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): **copy row** button in Table view produces unexpected result. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6421) and [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6495).
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/metricsql/): properly calculate [histogram_quantile](https://docs.victoriametrics.com/metricsql/#histogram_quantile) over Prometheus buckets with inconsistent values. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4580#issuecomment-2186659102) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6547). Updates [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2819).
|
||||
|
||||
## [v1.93.15](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.93.15)
|
||||
|
||||
Released at 2024-06-07
|
||||
|
||||
@@ -49,7 +49,8 @@ Further checks are optional for external contributions:
|
||||
|
||||
- The change must be described in **clear user-readable** form at [docs/CHANGELOG.md](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/docs/CHANGELOG.md),
|
||||
since it is read by **VictoriaMetrics users** who may not know implementation details of VictoriaMetrics products. The change description must **clearly** answer the following questions:
|
||||
- What does this change do?
|
||||
|
||||
- What does this change do? There is no need to provide technical details for the change, since they may confuse VictoriaMetrics users, who do not know Go.
|
||||
- Why this change is needed?
|
||||
|
||||
The change description must link to the related GitHub issues and the related docs, if any.
|
||||
|
||||
@@ -23,5 +23,5 @@ to [the latest available releases](https://docs.victoriametrics.com/changelog/).
|
||||
|
||||
## Currently supported LTS release lines
|
||||
|
||||
- 1.97.x - the latest one is [v1.97.5 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.5)
|
||||
- 1.93.x - the latest one is [v1.93.15 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.93.15)
|
||||
- 1.97.x - the latest one is [v1.97.6 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.97.6)
|
||||
- 1.93.x - the latest one is [v1.93.16 LTS release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.93.16)
|
||||
|
||||
@@ -617,13 +617,13 @@ VictoriaMetrics performs the following transformations to the ingested InfluxDB
|
||||
|
||||
For example, the following InfluxDB line:
|
||||
|
||||
```raw
|
||||
```influxtextmetric
|
||||
foo,tag1=value1,tag2=value2 field1=12,field2=40
|
||||
```
|
||||
|
||||
is converted into the following Prometheus data points:
|
||||
|
||||
```raw
|
||||
```promtextmetric
|
||||
foo_field1{tag1="value1", tag2="value2"} 12
|
||||
foo_field2{tag1="value1", tag2="value2"} 40
|
||||
```
|
||||
@@ -702,23 +702,21 @@ Example for writing data with Graphite plaintext protocol to local VictoriaMetri
|
||||
echo "foo.bar.baz;tag1=value1;tag2=value2 123 `date +%s`" | nc -N localhost 2003
|
||||
```
|
||||
|
||||
To sanitize ingested metric names and labels according to Prometheus naming convention enable
|
||||
`-graphite.sanitizeMetricName` cmd-line flag. When enabled, VictoriaMetrics will apply the following modifications:
|
||||
- replace `/`,`@`,`*` with `_`;
|
||||
- drop `\`;
|
||||
- remove redundant dots, e.g: `metric..name` => `metric.name`;
|
||||
- replace characters not matching the expression `^a-zA-Z0-9:._` with `_`.
|
||||
The ingested metrics can be sanitized according to Prometheus naming convention by passing `-graphite.sanitizeMetricName` command-line flag
|
||||
to VictoriaMetrics. The following modifications are applied to the ingested samples when this flag is passed to VictoriaMetrics:
|
||||
|
||||
- remove redundant dots, e.g: `metric..name` => `metric.name`
|
||||
- replace characters not matching `a-zA-Z0-9:_.` chars with `_`
|
||||
|
||||
VictoriaMetrics sets the current time to the ingested samples if the timestamp is omitted.
|
||||
|
||||
VictoriaMetrics sets the current time if the timestamp is omitted.
|
||||
An arbitrary number of lines delimited by `\n` (aka newline char) can be sent in one go.
|
||||
After that the data may be read via [/api/v1/export](#how-to-export-data-in-json-line-format) endpoint:
|
||||
|
||||
|
||||
```sh
|
||||
curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz'
|
||||
```
|
||||
|
||||
|
||||
The `/api/v1/export` endpoint should return the following response:
|
||||
|
||||
```json
|
||||
@@ -2648,24 +2646,30 @@ It is built from `*.md` files located in [docs](https://github.com/VictoriaMetri
|
||||
and gets automatically updated once changes are merged to [master](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master) branch.
|
||||
To update the documentation follow the steps below:
|
||||
- [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks)
|
||||
VictoriaMetrics repo and apply changes to the docs:
|
||||
VictoriaMetrics repo and apply changes to the docs:
|
||||
- To update [the main page](https://docs.victoriametrics.com/) modify [this file](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md).
|
||||
- To update other pages, apply changes to the corresponding file in [docs folder](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/docs).
|
||||
- If your changes contain an image then see [images in documentation](https://docs.victoriametrics.com/#images-in-documentation).
|
||||
- Once changes are made, execute the command below to finalize and sync the changes:
|
||||
```sh
|
||||
make docs-sync
|
||||
```
|
||||
|
||||
```sh
|
||||
make docs-sync
|
||||
```
|
||||
|
||||
- Create [a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
|
||||
with proposed changes and wait for it to be merged.
|
||||
with proposed changes and wait for it to be merged.
|
||||
|
||||
Requirements for changes to docs:
|
||||
|
||||
- Keep backward compatibility of existing links. Avoid changing anchors or deleting pages as they could have been
|
||||
used or posted in other docs, GitHub issues, stackoverlow answers, etc.
|
||||
- Keep docs simple. Try using as simple wording as possible.
|
||||
used or posted in other docs, GitHub issues, stackoverlow answers, etc.
|
||||
- Keep docs clear, concise and simple. Try using as simple wording as possible, without loosing the clarity.
|
||||
- Keep docs consistent. When modifying existing docs, verify that other places referencing to this doc are still relevant.
|
||||
- Prefer improving the existing docs instead of adding new ones.
|
||||
- Use absolute links.
|
||||
- Use absolute links. This simplifies moving docs between different files.
|
||||
|
||||
Priodically run `make spellcheck` - this command detects spelling errors at `docs/` folder. Please fix the found spelling errors
|
||||
and commit the fixes in a separate commit.
|
||||
|
||||
### Images in documentation
|
||||
|
||||
@@ -2673,6 +2677,10 @@ Please, keep image size and number of images per single page low. Keep the docs
|
||||
|
||||
Image files must be placed in the same folder as the doc itself and they must have the same prefix as the doc filename.
|
||||
For example, all the images for `docs/foo/bar.md` should have filenames starting from `docs/foo/bar`.
|
||||
This simplifies lifetime management of the images:
|
||||
|
||||
- when the corresponding doc is removed, then it is clear how to remove the associated images
|
||||
- when the corresponding doc is renamed, then it is clear how to rename the associated images.
|
||||
|
||||
If the page needs to have many images, consider using WEB-optimized image format [webp](https://developers.google.com/speed/webp).
|
||||
When adding a new doc with many images use `webp` format right away. Or use a Makefile command below to
|
||||
|
||||
@@ -159,32 +159,14 @@ Once updated, run the following commands:
|
||||
|
||||
## Ansible Roles
|
||||
|
||||
### Bump the version of images
|
||||
|
||||
Repository [https://github.com/VictoriaMetrics/ansible-playbooks](https://github.com/VictoriaMetrics/ansible-playbooks)
|
||||
|
||||
1. Update `vmagent` version in [`main.yml`](https://github.com/VictoriaMetrics/ansible-playbooks/blob/master/roles/vmagent/defaults/main.yml#L4)
|
||||
1. Update `vmalert` version in [`main.yml`](https://github.com/VictoriaMetrics/ansible-playbooks/blob/master/roles/vmalert/defaults/main.yml#L4)
|
||||
1. Update `cluster` version in [`main.yml`](https://github.com/VictoriaMetrics/ansible-playbooks/blob/master/roles/cluster/defaults/main.yml#L3)
|
||||
1. Update `single` version in [`main.yml`](https://github.com/VictoriaMetrics/ansible-playbooks/blob/master/roles/single/defaults/main.yml#L6)
|
||||
1. Commit changes
|
||||
1. Create a new tag
|
||||
1. Create a new release. This automatically publishes the new versions to galaxy.ansible.com
|
||||
1. Update the version of VictoriaMetrics components at [https://github.com/VictoriaMetrics/ansible-playbooks](https://github.com/VictoriaMetrics/ansible-playbooks).
|
||||
1. Commit changes.
|
||||
1. Create a new tag with `git tag -sm <TAG> <TAG>`.
|
||||
1. Push the changes with the new tag. This automatically publishes the new versions to galaxy.ansible.com.
|
||||
|
||||
## RPM packages
|
||||
|
||||
### Bump the version of components
|
||||
|
||||
Repository [https://github.com/VictoriaMetrics/victoriametrics-lts-rpm](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm)
|
||||
|
||||
1. Update `vmagent` version in [`vmagent.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmagent.spec#L2)
|
||||
1. Update `vmalert` version in [`vmalert.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmalert.spec#L2)
|
||||
1. Update `vmauth` version in [`vmauth.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmauth.spec#L2)
|
||||
1. Update `vmbackup` version in [`vmbackup.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmbackup.spec#L2)
|
||||
1. Update `vmctl` version in [`vmctl.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmctl.spec#L2)
|
||||
1. Update `vmrestore` version in [`vmrestore.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmrestore.spec#L2)
|
||||
1. Update `vminsert` version in [`vminsert.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vminsert.spec#L2)
|
||||
1. Update `vmselect` version in [`vmselect.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmselect.spec#L2)
|
||||
1. Update `vmstorage` version in [`vmstorage.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmstorage.spec#L2)
|
||||
1. Update `vmsingle` version in [`vmsingle.spec`](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm/blob/master/vmsingle.spec#L2)
|
||||
1. Update the version of VictoriaMetrics components at [https://github.com/VictoriaMetrics/victoriametrics-lts-rpm](https://github.com/VictoriaMetrics/victoriametrics-lts-rpm).
|
||||
1. Commit and push changes to the repository. This will automatically build and publish new versions of RPM packages.
|
||||
|
||||
@@ -625,13 +625,13 @@ VictoriaMetrics performs the following transformations to the ingested InfluxDB
|
||||
|
||||
For example, the following InfluxDB line:
|
||||
|
||||
```raw
|
||||
```influxtextmetric
|
||||
foo,tag1=value1,tag2=value2 field1=12,field2=40
|
||||
```
|
||||
|
||||
is converted into the following Prometheus data points:
|
||||
|
||||
```raw
|
||||
```promtextmetric
|
||||
foo_field1{tag1="value1", tag2="value2"} 12
|
||||
foo_field2{tag1="value1", tag2="value2"} 40
|
||||
```
|
||||
@@ -710,23 +710,21 @@ Example for writing data with Graphite plaintext protocol to local VictoriaMetri
|
||||
echo "foo.bar.baz;tag1=value1;tag2=value2 123 `date +%s`" | nc -N localhost 2003
|
||||
```
|
||||
|
||||
To sanitize ingested metric names and labels according to Prometheus naming convention enable
|
||||
`-graphite.sanitizeMetricName` cmd-line flag. When enabled, VictoriaMetrics will apply the following modifications:
|
||||
- replace `/`,`@`,`*` with `_`;
|
||||
- drop `\`;
|
||||
- remove redundant dots, e.g: `metric..name` => `metric.name`;
|
||||
- replace characters not matching the expression `^a-zA-Z0-9:._` with `_`.
|
||||
The ingested metrics can be sanitized according to Prometheus naming convention by passing `-graphite.sanitizeMetricName` command-line flag
|
||||
to VictoriaMetrics. The following modifications are applied to the ingested samples when this flag is passed to VictoriaMetrics:
|
||||
|
||||
- remove redundant dots, e.g: `metric..name` => `metric.name`
|
||||
- replace characters not matching `a-zA-Z0-9:_.` chars with `_`
|
||||
|
||||
VictoriaMetrics sets the current time to the ingested samples if the timestamp is omitted.
|
||||
|
||||
VictoriaMetrics sets the current time if the timestamp is omitted.
|
||||
An arbitrary number of lines delimited by `\n` (aka newline char) can be sent in one go.
|
||||
After that the data may be read via [/api/v1/export](#how-to-export-data-in-json-line-format) endpoint:
|
||||
|
||||
|
||||
```sh
|
||||
curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz'
|
||||
```
|
||||
|
||||
|
||||
The `/api/v1/export` endpoint should return the following response:
|
||||
|
||||
```json
|
||||
@@ -2656,24 +2654,30 @@ It is built from `*.md` files located in [docs](https://github.com/VictoriaMetri
|
||||
and gets automatically updated once changes are merged to [master](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master) branch.
|
||||
To update the documentation follow the steps below:
|
||||
- [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks)
|
||||
VictoriaMetrics repo and apply changes to the docs:
|
||||
VictoriaMetrics repo and apply changes to the docs:
|
||||
- To update [the main page](https://docs.victoriametrics.com/) modify [this file](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md).
|
||||
- To update other pages, apply changes to the corresponding file in [docs folder](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/docs).
|
||||
- If your changes contain an image then see [images in documentation](https://docs.victoriametrics.com/#images-in-documentation).
|
||||
- Once changes are made, execute the command below to finalize and sync the changes:
|
||||
```sh
|
||||
make docs-sync
|
||||
```
|
||||
|
||||
```sh
|
||||
make docs-sync
|
||||
```
|
||||
|
||||
- Create [a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
|
||||
with proposed changes and wait for it to be merged.
|
||||
with proposed changes and wait for it to be merged.
|
||||
|
||||
Requirements for changes to docs:
|
||||
|
||||
- Keep backward compatibility of existing links. Avoid changing anchors or deleting pages as they could have been
|
||||
used or posted in other docs, GitHub issues, stackoverlow answers, etc.
|
||||
- Keep docs simple. Try using as simple wording as possible.
|
||||
used or posted in other docs, GitHub issues, stackoverlow answers, etc.
|
||||
- Keep docs clear, concise and simple. Try using as simple wording as possible, without loosing the clarity.
|
||||
- Keep docs consistent. When modifying existing docs, verify that other places referencing to this doc are still relevant.
|
||||
- Prefer improving the existing docs instead of adding new ones.
|
||||
- Use absolute links.
|
||||
- Use absolute links. This simplifies moving docs between different files.
|
||||
|
||||
Priodically run `make spellcheck` - this command detects spelling errors at `docs/` folder. Please fix the found spelling errors
|
||||
and commit the fixes in a separate commit.
|
||||
|
||||
### Images in documentation
|
||||
|
||||
@@ -2681,6 +2685,10 @@ Please, keep image size and number of images per single page low. Keep the docs
|
||||
|
||||
Image files must be placed in the same folder as the doc itself and they must have the same prefix as the doc filename.
|
||||
For example, all the images for `docs/foo/bar.md` should have filenames starting from `docs/foo/bar`.
|
||||
This simplifies lifetime management of the images:
|
||||
|
||||
- when the corresponding doc is removed, then it is clear how to remove the associated images
|
||||
- when the corresponding doc is renamed, then it is clear how to rename the associated images.
|
||||
|
||||
If the page needs to have many images, consider using WEB-optimized image format [webp](https://developers.google.com/speed/webp).
|
||||
When adding a new doc with many images use `webp` format right away. Or use a Makefile command below to
|
||||
|
||||
@@ -46,7 +46,7 @@ from the received Syslog lines:
|
||||
- [`_msg`](https://docs.victoriametrics.com/victorialogs/keyconcepts/#message-field) - the `MESSAGE` field from the supported syslog formats above
|
||||
- `hostname`, `app_name` and `proc_id` - [stream fields](https://docs.victoriametrics.com/victorialogs/keyconcepts/#stream-fields) for unique identification
|
||||
over every log stream
|
||||
- `priority`, `factility` and `severity` - these fields are extracted from `<PRI>` field
|
||||
- `priority`, `facility` and `severity` - these fields are extracted from `<PRI>` field
|
||||
- `format` - this field is set to either `rfc3164` or `rfc5424` depending on the format of the parsed syslog line
|
||||
- `msg_id` - `MSGID` field from log line in `RFC5424` format.
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ aliases:
|
||||
via the following ways:
|
||||
|
||||
- [Web UI](#web-ui) - a web-based UI for querying logs
|
||||
- [Visualization in Grafana](#visualization-in-grafana)
|
||||
- [HTTP API](#http-api)
|
||||
- [Command-line interface](#command-line)
|
||||
|
||||
|
||||
@@ -15,7 +15,11 @@ aliases:
|
||||
|
||||
Please find the changelog for VictoriaMetrics Anomaly Detection below.
|
||||
|
||||
> **Important note: Users are strongly encouraged to upgrade to `vmanomaly` [v1.9.2](https://hub.docker.com/repository/docker/victoriametrics/vmanomaly/tags?page=1&ordering=name) or newer for optimal performance and accuracy. <br><br> This recommendation is crucial for configurations with a low `infer_every` parameter [in your scheduler](https://docs.victoriametrics.com/anomaly-detection/components/scheduler/#parameters-1), and in scenarios where data exhibits significant high-order seasonality patterns (such as hourly or daily cycles). Previous versions from v1.5.1 to v1.8.0 were identified to contain a critical issue impacting model training, where models were inadvertently trained on limited data subsets, leading to suboptimal fits, affecting the accuracy of anomaly detection. <br><br> Upgrading to v1.9.2 addresses this issue, ensuring proper model training and enhanced reliability. For users utilizing Helm charts, it is recommended to upgrade to version [1.0.0](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-anomaly/CHANGELOG.md#100) or newer.**
|
||||
> **Important note: Users are strongly encouraged to upgrade to `vmanomaly` [v1.9.2](https://hub.docker.com/repository/docker/victoriametrics/vmanomaly/tags?page=1&ordering=name) or newer for optimal performance and accuracy. <br><br> This recommendation is crucial for configurations with a low `infer_every` parameter [in your scheduler](/anomaly-detection/components/scheduler/#parameters-1), and in scenarios where data exhibits significant high-order seasonality patterns (such as hourly or daily cycles). Previous versions from v1.5.1 to v1.8.0 were identified to contain a critical issue impacting model training, where models were inadvertently trained on limited data subsets, leading to suboptimal fits, affecting the accuracy of anomaly detection. <br><br> Upgrading to v1.9.2 addresses this issue, ensuring proper model training and enhanced reliability. For users utilizing Helm charts, it is recommended to upgrade to version [1.0.0](https://github.com/VictoriaMetrics/helm-charts/blob/master/charts/victoria-metrics-anomaly/CHANGELOG.md#100) or newer.**
|
||||
|
||||
## v1.13.3
|
||||
Released: 2024-07-17
|
||||
- FIX: now validation of `args` argument for [`HoltWinters`](/anomaly-detection/components/models#holt-winters) model works properly.
|
||||
|
||||
## v1.13.2
|
||||
Released: 2024-07-15
|
||||
|
||||
@@ -19,9 +19,9 @@ aliases:
|
||||
|
||||
- To use *vmanomaly*, part of the enterprise package, a license key is required. Obtain your key [here](https://victoriametrics.com/products/enterprise/trial/) for this tutorial or for enterprise use.
|
||||
- In the tutorial, we'll be using the following VictoriaMetrics components:
|
||||
- [VictoriaMetrics Single-Node](https://docs.victoriametrics.com/single-server-victoriametrics/) (v1.101.0)
|
||||
- [vmalert](https://docs.victoriametrics.com/vmalert/) (v1.101.0)
|
||||
- [vmagent](https://docs.victoriametrics.com/vmagent/) (v1.101.0)
|
||||
- [VictoriaMetrics Single-Node](https://docs.victoriametrics.com/single-server-victoriametrics/) (v1.102.0)
|
||||
- [vmalert](https://docs.victoriametrics.com/vmalert/) (v1.102.0)
|
||||
- [vmagent](https://docs.victoriametrics.com/vmagent/) (v1.102.0)
|
||||
- [Grafana](https://grafana.com/) (v.10.2.1)
|
||||
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/)
|
||||
- [Node exporter](https://github.com/prometheus/node_exporter#node-exporter) (v1.7.0) and [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (v0.27.0)
|
||||
@@ -330,7 +330,7 @@ Let's wrap it all up together into the `docker-compose.yml` file.
|
||||
services:
|
||||
vmagent:
|
||||
container_name: vmagent
|
||||
image: victoriametrics/vmagent:v1.101.0
|
||||
image: victoriametrics/vmagent:v1.102.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
@@ -347,7 +347,7 @@ services:
|
||||
|
||||
victoriametrics:
|
||||
container_name: victoriametrics
|
||||
image: victoriametrics/victoria-metrics:v1.101.0
|
||||
image: victoriametrics/victoria-metrics:v1.102.0
|
||||
ports:
|
||||
- 8428:8428
|
||||
volumes:
|
||||
@@ -380,7 +380,7 @@ services:
|
||||
|
||||
vmalert:
|
||||
container_name: vmalert
|
||||
image: victoriametrics/vmalert:v1.101.0
|
||||
image: victoriametrics/vmalert:v1.102.0
|
||||
depends_on:
|
||||
- "victoriametrics"
|
||||
ports:
|
||||
|
||||
@@ -118,4 +118,4 @@ sinks:
|
||||
|
||||
# References
|
||||
- [Vector documentation](https://vector.dev/docs/)
|
||||
- [VictoriaLogs documenation for using vector]({{< ref "/victorialogs/data-ingestion/vector" >}})
|
||||
- [VictoriaLogs documentation for using vector]({{< ref "/victorialogs/data-ingestion/vector" >}})
|
||||
|
||||
@@ -85,7 +85,7 @@ VictoriaMetrics Enterprise components are available in the following forms:
|
||||
It is allowed to run VictoriaMetrics Enterprise components in [cases listed here](#valid-cases-for-victoriametrics-enterprise).
|
||||
|
||||
Binary releases of VictoriaMetrics Enterprise are available [at the releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
|
||||
Enterprise binaries and packages have `enterprise` suffix in their names. For example, `victoria-metrics-linux-amd64-v1.101.0-enterprise.tar.gz`.
|
||||
Enterprise binaries and packages have `enterprise` suffix in their names. For example, `victoria-metrics-linux-amd64-v1.102.0-enterprise.tar.gz`.
|
||||
|
||||
In order to run binary release of VictoriaMetrics Enterprise component, please download the `*-enterprise.tar.gz` archive for your OS and architecture
|
||||
from the [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest) and unpack it. Then run the unpacked binary.
|
||||
@@ -102,8 +102,8 @@ For example, the following command runs VictoriaMetrics Enterprise binary with t
|
||||
obtained at [this page](https://victoriametrics.com/products/enterprise/trial/):
|
||||
|
||||
```sh
|
||||
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.101.0/victoria-metrics-linux-amd64-v1.101.0-enterprise.tar.gz
|
||||
tar -xzf victoria-metrics-linux-amd64-v1.101.0-enterprise.tar.gz
|
||||
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.102.0/victoria-metrics-linux-amd64-v1.102.0-enterprise.tar.gz
|
||||
tar -xzf victoria-metrics-linux-amd64-v1.102.0-enterprise.tar.gz
|
||||
./victoria-metrics-prod -license=BASE64_ENCODED_LICENSE_KEY
|
||||
```
|
||||
|
||||
@@ -118,7 +118,7 @@ Alternatively, VictoriaMetrics Enterprise license can be stored in the file and
|
||||
It is allowed to run VictoriaMetrics Enterprise components in [cases listed here](#valid-cases-for-victoriametrics-enterprise).
|
||||
|
||||
Docker images for VictoriaMetrics Enterprise are available [at VictoriaMetrics DockerHub](https://hub.docker.com/u/victoriametrics).
|
||||
Enterprise docker images have `enterprise` suffix in their names. For example, `victoriametrics/victoria-metrics:v1.101.0-enterprise`.
|
||||
Enterprise docker images have `enterprise` suffix in their names. For example, `victoriametrics/victoria-metrics:v1.102.0-enterprise`.
|
||||
|
||||
In order to run Docker image of VictoriaMetrics Enterprise component, it is required to provide the license key via command-line
|
||||
flag as described [here](#binary-releases).
|
||||
@@ -128,13 +128,13 @@ Enterprise license key can be obtained at [this page](https://victoriametrics.co
|
||||
For example, the following command runs VictoriaMetrics Enterprise Docker image with the specified license key:
|
||||
|
||||
```sh
|
||||
docker run --name=victoria-metrics victoriametrics/victoria-metrics:v1.101.0-enterprise -license=BASE64_ENCODED_LICENSE_KEY
|
||||
docker run --name=victoria-metrics victoriametrics/victoria-metrics:v1.102.0-enterprise -license=BASE64_ENCODED_LICENSE_KEY
|
||||
```
|
||||
|
||||
Alternatively, the license code can be stored in the file and then referred via `-licenseFile` command-line flag:
|
||||
|
||||
```sh
|
||||
docker run --name=victoria-metrics -v /vm-license:/vm-license victoriametrics/victoria-metrics:v1.101.0-enterprise -licenseFile=/path/to/vm-license
|
||||
docker run --name=victoria-metrics -v /vm-license:/vm-license victoriametrics/victoria-metrics:v1.102.0-enterprise -licenseFile=/path/to/vm-license
|
||||
```
|
||||
|
||||
Example docker-compose configuration:
|
||||
@@ -143,7 +143,7 @@ version: "3.5"
|
||||
services:
|
||||
victoriametrics:
|
||||
container_name: victoriametrics
|
||||
image: victoriametrics/victoria-metrics:v1.101.0
|
||||
image: victoriametrics/victoria-metrics:v1.102.0
|
||||
ports:
|
||||
- 8428:8428
|
||||
volumes:
|
||||
@@ -175,7 +175,7 @@ is used to provide key in plain-text:
|
||||
```yaml
|
||||
server:
|
||||
image:
|
||||
tag: v1.101.0-enterprise
|
||||
tag: v1.102.0-enterprise
|
||||
|
||||
license:
|
||||
key: {BASE64_ENCODED_LICENSE_KEY}
|
||||
@@ -186,7 +186,7 @@ In order to provide key via existing secret, the following values file is used:
|
||||
```yaml
|
||||
server:
|
||||
image:
|
||||
tag: v1.101.0-enterprise
|
||||
tag: v1.102.0-enterprise
|
||||
|
||||
license:
|
||||
secret:
|
||||
@@ -233,7 +233,7 @@ spec:
|
||||
license:
|
||||
key: {BASE64_ENCODED_LICENSE_KEY}
|
||||
image:
|
||||
tag: v1.101.0-enterprise
|
||||
tag: v1.102.0-enterprise
|
||||
```
|
||||
|
||||
In order to provide key via existing secret, the following custom resource is used:
|
||||
@@ -250,7 +250,7 @@ spec:
|
||||
name: vm-license
|
||||
key: license
|
||||
image:
|
||||
tag: v1.101.0-enterprise
|
||||
tag: v1.102.0-enterprise
|
||||
```
|
||||
|
||||
Example secret with license key:
|
||||
|
||||
@@ -23,7 +23,7 @@ menu:
|
||||
upgrade to [the latest available release](https://docs.victoriametrics.com/CHANGELOG.html) and remain happy.
|
||||
1. Improving usability for the existing functionality of VictoriaMetrics components.
|
||||
1. Improving the readability and maintainability of the code base by removing unnecessary abstractions and simplifying the code whenever possible.
|
||||
1. Improving development velocity by optimizing CI/CD tasks, so they take less time.
|
||||
1. Improving development velocity by optimizing and simplifying CI/CD tasks, so they take less time.
|
||||
|
||||
## Non-goals
|
||||
|
||||
@@ -40,8 +40,8 @@ menu:
|
||||
Other feature requests must be closed as `won't implement`, with the link to this page.
|
||||
1. Merging all the pull requests users submit. These pull requests should fit [the goals](#goals) of VictoriaMetrics.
|
||||
Other pull requests must be closed as `won't merge`, with the link to this page.
|
||||
1. Slowing down CI/CD pipelines with non-essential tasks, since this results in development velocity slowdown.
|
||||
1. Slowing down development velocity by introducing non-essential requirements.
|
||||
1. Slowing down and complicating CI/CD pipelines with non-essential tasks, since this results in development velocity slowdown.
|
||||
1. Introducing non-essential requrirements, since this slows down development velocity.
|
||||
|
||||
## VictoriaMetrics proverbs
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ scrape_configs:
|
||||
After you created the `scrape.yaml` file, download and unpack [single-node VictoriaMetrics](https://docs.victoriametrics.com/) to the same directory:
|
||||
|
||||
```
|
||||
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.101.0/victoria-metrics-linux-amd64-v1.101.0.tar.gz
|
||||
tar xzf victoria-metrics-linux-amd64-v1.101.0.tar.gz
|
||||
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.102.0/victoria-metrics-linux-amd64-v1.102.0.tar.gz
|
||||
tar xzf victoria-metrics-linux-amd64-v1.102.0.tar.gz
|
||||
```
|
||||
|
||||
Then start VictoriaMetrics and instruct it to scrape targets defined in `scrape.yaml` and save scraped metrics
|
||||
@@ -150,8 +150,8 @@ Then start [single-node VictoriaMetrics](https://docs.victoriametrics.com/) acco
|
||||
|
||||
```yaml
|
||||
# Download and unpack single-node VictoriaMetrics
|
||||
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.101.0/victoria-metrics-linux-amd64-v1.101.0.tar.gz
|
||||
tar xzf victoria-metrics-linux-amd64-v1.101.0.tar.gz
|
||||
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.102.0/victoria-metrics-linux-amd64-v1.102.0.tar.gz
|
||||
tar xzf victoria-metrics-linux-amd64-v1.102.0.tar.gz
|
||||
|
||||
# Run single-node VictoriaMetrics with the given scrape.yaml
|
||||
./victoria-metrics-prod -promscrape.config=scrape.yaml
|
||||
|
||||
@@ -1554,7 +1554,7 @@ The following meta labels are available on discovered targets during [relabeling
|
||||
|
||||
* `__meta_vultr_instance_allowed_bandwidth_gb`: monthly bandwidth quota in GB.
|
||||
* `__meta_vultr_instance_disk_gb`: the size of the disk in GB.
|
||||
* `__meta_vultr_instance_features`: comma-separated list of features avabilable to instance, such as "auto_backups", "ipv6", "ddos_protection".
|
||||
* `__meta_vultr_instance_features`: comma-separated list of features available to instance, such as "auto_backups", "ipv6", "ddos_protection".
|
||||
* `__meta_vultr_instance_hostname`: hostname for this instance.
|
||||
* `__meta_vultr_instance_id`: unique ID for the VPS Instance.
|
||||
* `__meta_vultr_instance_internal_ip`: internal IP used by this instance, if set. Only relevant when a VPC is attached.
|
||||
|
||||
@@ -44,7 +44,8 @@ This behaviour can be changed via the following command-line flags:
|
||||
|
||||
- `-streamAggr.keepInput` at [single-node VictoriaMetrics](https://docs.victoriametrics.com/single-server-victoriametrics/)
|
||||
and [vmagent](https://docs.victoriametrics.com/vmagent/). At [vmagent](https://docs.victoriametrics.com/vmagent/)
|
||||
`-remoteWrite.streamAggr.keepInput` flag can be specified individually per each `-remoteWrite.url`.
|
||||
`-remoteWrite.streamAggr.keepInput` flag can be specified individually per each `-remoteWrite.url` and `keep_input` parameter can be defined
|
||||
for each aggregator separately.
|
||||
If one of these flags is set, then all the input samples are written to the storage alongside the aggregated samples.
|
||||
- `-streamAggr.dropInput` at [single-node VictoriaMetrics](https://docs.victoriametrics.com/single-server-victoriametrics/)
|
||||
and [vmagent](https://docs.victoriametrics.com/vmagent/). At [vmagent](https://docs.victoriametrics.com/vmagent/)
|
||||
@@ -1016,6 +1017,7 @@ At [vmagent](https://docs.victoriametrics.com/vmagent/) `-remoteWrite.streamAggr
|
||||
specified individually per each `-remoteWrite.url`:
|
||||
|
||||
```yaml
|
||||
|
||||
# name is an optional name of the given streaming aggregation config.
|
||||
#
|
||||
# If it is set, then it is used as `name` label in the exposed metrics
|
||||
@@ -1031,7 +1033,7 @@ specified individually per each `-remoteWrite.url`:
|
||||
# match also can contain a list of series selectors. Then the incoming samples are aggregated
|
||||
# if they match at least a single series selector.
|
||||
#
|
||||
- match: 'http_request_duration_seconds_bucket{env=~"prod|staging"}'
|
||||
match: 'http_request_duration_seconds_bucket{env=~"prod|staging"}'
|
||||
|
||||
# interval is the interval for the aggregation.
|
||||
# The aggregated stats is sent to remote storage once per interval.
|
||||
|
||||
@@ -1260,7 +1260,7 @@ See the docs at https://docs.victoriametrics.com/vmauth/ .
|
||||
-maxIdleConnsPerBackend int
|
||||
The maximum number of idle connections vmauth can open per each backend host. See also -maxConcurrentRequests (default 100)
|
||||
-maxRequestBodySizeToRetry size
|
||||
The maximum request body size, which can be cached and re-tried at other backends. Bigger values may require more memory. Negative or zero values disable request body caching and retries.
|
||||
The maximum request body size, which can be cached and re-tried at other backends. Bigger values may require more memory. Zero or negative value disables caching of request body. This may be useful when proxying data ingestion requests
|
||||
Supports the following optional suffixes for size values: KB, MB, GB, TB, KiB, MiB, GiB, TiB (default 16384)
|
||||
-memory.allowedBytes size
|
||||
Allowed size of system memory VictoriaMetrics caches may occupy. This option overrides -memory.allowedPercent if set to a non-zero value. Too low a value may increase the cache miss rate usually resulting in higher CPU and disk IO usage. Too high a value may evict too much data from the OS page cache resulting in higher disk IO usage
|
||||
|
||||
@@ -207,10 +207,12 @@ Obtaining credentials from env variables.
|
||||
Also you can set env variable `AWS_SHARED_CREDENTIALS_FILE` with path to credentials file.
|
||||
- For GCE cloud storage set env variable `GOOGLE_APPLICATION_CREDENTIALS` with path to credentials file.
|
||||
- For Azure storage use one of these env variables:
|
||||
- `AZURE_STORAGE_ACCOUNT_NAME` and `AZURE_STORAGE_ACCOUNT_KEY`: Use a specific account name and key (either primary or secondary).
|
||||
- `AZURE_STORAGE_ACCOUNT_CONNECTION_STRING`: Use a connection string (must be either SAS Token or Account/Key)
|
||||
- `AZURE_USE_DEFAULT_CREDENTIAL` and `AZURE_STORAGE_ACCOUNT_NAME`: Use the `DefaultAzureCredential` to allow the azure library to search multiple options (for example, managed identity related variables).
|
||||
- `AZURE_STORAGE_DOMAIN`: Optionally override the default blob domain for the Azure storage service.
|
||||
- `AZURE_STORAGE_ACCOUNT_CONNECTION_STRING`: use a connection string (must be either SAS Token or Account/Key)
|
||||
- `AZURE_STORAGE_ACCOUNT_NAME` and `AZURE_STORAGE_ACCOUNT_KEY`: use a specific account name and key (either primary or secondary)
|
||||
- `AZURE_USE_DEFAULT_CREDENTIAL` and `AZURE_STORAGE_ACCOUNT_NAME`: use the `DefaultAzureCredential` to allow the Azure library
|
||||
to search for multiple options (for example, managed identity related variables).
|
||||
|
||||
The `AZURE_STORAGE_DOMAIN` can be used for optionally overriding the default domain for the Azure storage service.
|
||||
|
||||
Please, note that `vmbackup` will use credentials provided by cloud providers metadata service [when applicable](https://docs.victoriametrics.com/vmbackup/#using-cloud-providers-metadata-service).
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ i.e. the end result would be similar to [rsync --delete](https://askubuntu.com/q
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* See [how to setup credentials via environment variables](https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables).
|
||||
* If `vmrestore` eats all the network bandwidth, then set `-maxBytesPerSecond` to the desired value.
|
||||
* If `vmrestore` has been interrupted due to temporary error, then just restart it with the same args. It will resume the restore process.
|
||||
|
||||
|
||||
56
go.mod
56
go.mod
@@ -4,17 +4,17 @@ go 1.22.5
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.43.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
|
||||
github.com/VictoriaMetrics/easyproto v0.1.4
|
||||
github.com/VictoriaMetrics/fastcache v1.12.2
|
||||
github.com/VictoriaMetrics/metrics v1.35.1
|
||||
github.com/VictoriaMetrics/metricsql v0.76.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.1
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.24
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.5
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.26
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.7
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1
|
||||
github.com/cespare/xxhash/v2 v2.3.0
|
||||
github.com/cheggaaa/pb/v3 v3.1.5
|
||||
@@ -39,29 +39,29 @@ require (
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.115.0 // indirect
|
||||
cloud.google.com/go/auth v0.7.0 // indirect
|
||||
cloud.google.com/go/auth v0.7.1 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.4.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.10 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.11 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect
|
||||
github.com/aws/aws-sdk-go v1.54.17 // indirect
|
||||
github.com/aws/aws-sdk-go v1.54.19 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
|
||||
github.com/aws/smithy-go v1.20.3 // indirect
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
@@ -107,8 +107,8 @@ require (
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.11.0 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.104.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.12.0 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.105.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
@@ -118,19 +118,19 @@ require (
|
||||
go.uber.org/goleak v1.3.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.25.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect
|
||||
golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect
|
||||
google.golang.org/grpc v1.65.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apimachinery v0.30.2 // indirect
|
||||
k8s.io/client-go v0.30.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||
)
|
||||
|
||||
112
go.sum
112
go.sum
@@ -15,8 +15,8 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14=
|
||||
cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU=
|
||||
cloud.google.com/go/auth v0.7.0 h1:kf/x9B3WTbBUHkC+1VS8wwwli9TzhSt0vSTVBmMR8Ts=
|
||||
cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw=
|
||||
cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s=
|
||||
cloud.google.com/go/auth v0.7.1/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
@@ -25,12 +25,12 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c=
|
||||
cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M=
|
||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/iam v1.1.10 h1:ZSAr64oEhQSClwBL670MsJAW5/RLiC6kfw3Bqmd5ZDI=
|
||||
cloud.google.com/go/iam v1.1.10/go.mod h1:iEgMq62sg8zx446GCaijmA2Miwg5o3UbO+nI47WHJps=
|
||||
cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw=
|
||||
cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ=
|
||||
cloud.google.com/go/longrunning v0.5.9 h1:haH9pAuXdPAMqHvzX0zlWQigXT7B0+CL4/2nXXdBo5k=
|
||||
cloud.google.com/go/longrunning v0.5.9/go.mod h1:HD+0l9/OOW0za6UWdKJtXoFAX/BGg/3Wj8p10NeWF7c=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
@@ -45,12 +45,12 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
||||
cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs=
|
||||
cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 h1:GJHeeA2N7xrG3q30L2UXDyuWRzDM900/65j70wcM4Ww=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.1 h1:Xy/qV1DyOhhqsU/z0PyFMJfYCxnzna+vBEUtFW0ksQo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.1/go.mod h1:oib6iWdC+sILvNUoJbbBn3xv7TXow7mEp/WRcsYvmow=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
|
||||
@@ -90,44 +90,44 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax
|
||||
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.54.17 h1:ZV/qwcCIhMHgsJ6iXXPVYI0s1MdLT+5LW28ClzCUPeI=
|
||||
github.com/aws/aws-sdk-go v1.54.17/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.1 h1:4y/5Dvfrhd1MxRDD77SrfsDaj8kUkkljU7XE83NPV+o=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.1/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
|
||||
github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI=
|
||||
github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.24 h1:NM9XicZ5o1CBU/MZaHwFtimRpWx9ohAUAqkG6AqSqPo=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.24/go.mod h1:aXzi6QJTuQRVVusAO8/NxpdTeTyr/wRcybdDtfUwJSs=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.24 h1:YclAsrnb1/GTQNt2nzv+756Iw4mF8AOzcDfweWwwm/M=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.24/go.mod h1:Hld7tmnAkoBQdTMNYZGzztzKRdA4fCdn9L83LOoigac=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 h1:Aznqksmd6Rfv2HQN9cpqIV/lQRMaIpJkLLaJ1ZI76no=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9/go.mod h1:WQr3MY7AxGNxaqAtsDWn+fBxmd4XvLkzeqQ8P1VM0/w=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.5 h1:qkipTyOc+ElVS+TgGJCf/6gqu0CL5+ii19W/eMQfY94=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.5/go.mod h1:UjB35RXl+ESpnVtyaKqdw11NhMxm90lF9o2zqJNbi14=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13 h1:5SAoZ4jYpGH4721ZNoS1znQrhOfZinOhc4XuTXx/nVc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13/go.mod h1:+rdA6ZLpaSeM7tSg/B0IEDinCIBJGmW8rKDFkYpP04g=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13 h1:WIijqeaAO7TYFLbhsZmi2rgLEAtWOC1LhxCAVTJlSKw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13/go.mod h1:i+kbfa76PQbWw/ULoWnp51EYVWH4ENln76fLQE3lXT8=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.26 h1:T1kAefbKuNum/AbShMsZEro6eRkeOT8YILfE9wyjAYQ=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.26/go.mod h1:ivWHkAWFrw/nxty5Fku7soTIVdqZaZ7dw+tc5iGW3GA=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.26 h1:tsm8g/nJxi8+/7XyJJcP2dLrnK/5rkFp6+i2nhmz5fk=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.26/go.mod h1:3vAM49zkIa3q8WT6o9Ve5Z0vdByDMwmdScO0zvThTgI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.7 h1:kNemAUX+bJFBSfPkGVZ8HFOKIadjLoI2Ua1ZKivhGSo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.7/go.mod h1:71S2C1g/Zjn+ANmyoOqJ586OrPF9uC9iiHt9ZAT+MOw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.13 h1:THZJJ6TU/FOiM7DZFnisYV9d49oxXWUzsVIMTuf3VNU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.13/go.mod h1:VISUTg6n+uBaYIWPBaIG0jk7mbBxm7DUqBtU2cUDDWI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15 h1:Z5r7SycxmSllHYmaAZPpmN8GviDrSGhMS6bldqtXZPw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15/go.mod h1:CetW7bDE00QoGEmPUoZuRog07SGVAUVW6LFpNP0YfIg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.15 h1:2jyRZ9rVIMisyQRnhSS/SqlckveoxXneIumECVFP91Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.15/go.mod h1:bDRG3m382v1KJBk1cKz7wIajg87/61EiiymEyfLvAe0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15 h1:I9zMeF107l0rJrpnHpjEiiTSCKYAIw8mALiXcPsGBiA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15/go.mod h1:9xWJ3Q/S6Ojusz1UIkfycgD1mGirJfLLKqq3LPT7WN8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.13 h1:Eq2THzHt6P41mpjS2sUzz/3dJYFRqdWZ+vQaEMm98EM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.13/go.mod h1:FgwTca6puegxgCInYwGjmd4tB9195Dd6LCuA+8MjpWw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.0 h1:4rhV0Hn+bf8IAIUphRX1moBcEvKJipCPmswMCl6Q5mw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.0/go.mod h1:hdV0NTYd0RwV4FvNKhKUNbPLZoq9CTr/lke+3I7aCAI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 h1:p1GahKIjyMDZtiKoIn0/jAj/TkMzfzndDv5+zi2Mhgc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.1/go.mod h1:/vWdhoIoYA5hYoPZ6fm7Sv4d8701PiG5VKe8/pPJL60=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 h1:ORnrOK0C4WmYV/uYt3koHEWBLYsRDwk2Np+eEoyV4Z0=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2/go.mod h1:xyFHA4zGxgYkdD73VeezHt3vSKEG9EmFnGwoKlP00u4=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 h1:+woJ607dllHJQtsnJLi52ycuqHMwlW+Wqm2Ppsfp4nQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.1/go.mod h1:jiNR3JqT15Dm+QWq2SRgh0x0bCNSRP2L25+CqPNpJlQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17 h1:YPYe6ZmvUfDDDELqEKtAd6bo8zxhkm+XEFEzQisqUIE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17/go.mod h1:oBtcnYua/CgzCWYN7NZ5j7PotFDaFSUjCYVTtfyn7vw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15 h1:246A4lSTXWJw/rmlQI+TT2OcqeDMKBdyjEQrafMaQdA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15/go.mod h1:haVfg3761/WF7YPuJOER2MP0k4UAXyHaLclKXB6usDg=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2 h1:sZXIzO38GZOU+O0C+INqbH7C2yALwfMWpd64tONS/NE=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2/go.mod h1:Lcxzg5rojyVPU/0eFwLtcyTaek/6Mtic5B1gJo7e/zE=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 h1:Fv1vD2L65Jnp5QRsdiM64JvUM4Xe+E0JyVsRQKv6IeA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
|
||||
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
|
||||
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps=
|
||||
@@ -515,10 +515,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/collector/pdata v1.11.0 h1:rzYyV1zfTQQz1DI9hCiaKyyaczqawN75XO9mdXmR/hE=
|
||||
go.opentelemetry.io/collector/pdata v1.11.0/go.mod h1:IHxHsp+Jq/xfjORQMDJjSH6jvedOSTOyu3nbxqhWSYE=
|
||||
go.opentelemetry.io/collector/semconv v0.104.0 h1:dUvajnh+AYJLEW/XOPk0T0BlwltSdi3vrjO7nSOos3k=
|
||||
go.opentelemetry.io/collector/semconv v0.104.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw=
|
||||
go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA=
|
||||
go.opentelemetry.io/collector/pdata v1.12.0/go.mod h1:MYeB0MmMAxeM0hstCFrCqWLzdyeYySim2dG6pDT6nYI=
|
||||
go.opentelemetry.io/collector/semconv v0.105.0 h1:8p6dZ3JfxFTjbY38d8xlQGB1TQ3nPUvs+D0RERniZ1g=
|
||||
go.opentelemetry.io/collector/semconv v0.105.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
@@ -555,8 +555,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w=
|
||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA=
|
||||
golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -793,12 +793,12 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5 h1:ORprMx6Xqr56pGwKXMnVEFBI0k7OIcHI0Rx92/rKypo=
|
||||
google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5 h1:a/Z0jgw03aJ2rQnp5PlPpznJqJft0HyvyrcUcxgzPwY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 h1:SbSDUWW1PAO24TNpLdeheoYPd7kllICcLU52x6eD4kQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||
google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc=
|
||||
google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -866,8 +866,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=
|
||||
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
||||
@@ -24,15 +24,6 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
envStorageAcctName = "AZURE_STORAGE_ACCOUNT_NAME"
|
||||
envStorageAccKey = "AZURE_STORAGE_ACCOUNT_KEY"
|
||||
envStorageAccCs = "AZURE_STORAGE_ACCOUNT_CONNECTION_STRING"
|
||||
envStorageDomain = "AZURE_STORAGE_DOMAIN"
|
||||
envStorageDefault = "AZURE_USE_DEFAULT_CREDENTIAL"
|
||||
storageErrorCodeBlobNotFound = "BlobNotFound"
|
||||
)
|
||||
|
||||
// FS represents filesystem for backups in Azure Blob Storage.
|
||||
//
|
||||
// Init must be called before calling other FS methods.
|
||||
@@ -44,18 +35,17 @@ type FS struct {
|
||||
Dir string
|
||||
|
||||
client *container.Client
|
||||
env envLookuper
|
||||
|
||||
// envLoookupFunc is used for looking up environment variables in tests.
|
||||
envLookupFunc func(name string) (string, bool)
|
||||
}
|
||||
|
||||
// Init initializes fs.
|
||||
//
|
||||
// The returned fs must be stopped when no long needed with MustStop call.
|
||||
func (fs *FS) Init() error {
|
||||
switch {
|
||||
case fs.client != nil:
|
||||
if fs.client != nil {
|
||||
logger.Panicf("BUG: fs.Init has been already called")
|
||||
case fs.env == nil:
|
||||
fs.env = envtemplate.LookupEnv
|
||||
}
|
||||
|
||||
fs.Dir = cleanDirectory(fs.Dir)
|
||||
@@ -72,58 +62,68 @@ func (fs *FS) Init() error {
|
||||
}
|
||||
|
||||
func (fs *FS) newClient() (*service.Client, error) {
|
||||
connString, hasConnString := fs.env(envStorageAccCs)
|
||||
accountName, hasAccountName := fs.env(envStorageAcctName)
|
||||
accountKey, hasAccountKey := fs.env(envStorageAccKey)
|
||||
useDefault, _ := fs.env(envStorageDefault)
|
||||
|
||||
domain := "blob.core.windows.net"
|
||||
if storageDomain, ok := fs.env(envStorageDomain); ok {
|
||||
logger.Infof("Overriding default Azure blob domain with %q", storageDomain)
|
||||
domain = storageDomain
|
||||
connString := fs.env("AZURE_STORAGE_ACCOUNT_CONNECTION_STRING")
|
||||
if connString != "" {
|
||||
logger.Infof("creating AZBlob service client from connection string defined at AZURE_STORAGE_ACCOUNT_CONNECTION_STRING")
|
||||
return service.NewClientFromConnectionString(connString, nil)
|
||||
}
|
||||
|
||||
// not used if connection string is set
|
||||
serviceURL := fmt.Sprintf("https://%s.%s/", accountName, domain)
|
||||
accountKey := fs.env("AZURE_STORAGE_ACCOUNT_KEY")
|
||||
if accountKey != "" {
|
||||
logger.Infof("creating AZBlob service client from account name and key")
|
||||
|
||||
switch {
|
||||
// can't specify any combination of more than one credential
|
||||
case moreThanOne(hasConnString, (hasAccountName && hasAccountKey), (useDefault == "true" && hasAccountName)):
|
||||
return nil, fmt.Errorf("failed to process credentials: only one of %s, %s and %s, or %s and %s can be specified",
|
||||
envStorageAccCs,
|
||||
envStorageAcctName,
|
||||
envStorageAccKey,
|
||||
envStorageAcctName,
|
||||
envStorageDefault,
|
||||
)
|
||||
case hasConnString:
|
||||
logger.Infof("Creating AZBlob service client from connection string")
|
||||
return service.NewClientFromConnectionString(connString, nil)
|
||||
case hasAccountName && hasAccountKey:
|
||||
logger.Infof("Creating AZBlob service client from account name and key")
|
||||
accountName := fs.env("AZURE_STORAGE_ACCOUNT_NAME")
|
||||
if accountName == "" {
|
||||
return nil, fmt.Errorf("missing AZURE_STORAGE_ACCOUNT_NAME environment variable when AZURE_STORAGE_ACCOUNT_KEY is set; " +
|
||||
"see https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables")
|
||||
}
|
||||
creds, err := azblob.NewSharedKeyCredential(accountName, accountKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create Shared Key credentials: %w", err)
|
||||
}
|
||||
serviceURL := fs.getServiceURL(accountName)
|
||||
return service.NewClientWithSharedKeyCredential(serviceURL, creds, nil)
|
||||
case useDefault == "true" && hasAccountName:
|
||||
logger.Infof("Creating AZBlob service client from default credential")
|
||||
}
|
||||
|
||||
useDefault := fs.env("AZURE_USE_DEFAULT_CREDENTIAL")
|
||||
if useDefault == "true" {
|
||||
logger.Infof("creating AZBlob service client from default credentials")
|
||||
creds, err := azidentity.NewDefaultAzureCredential(nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create default Azure credentials: %w", err)
|
||||
}
|
||||
|
||||
accountName := fs.env("AZURE_STORAGE_ACCOUNT_NAME")
|
||||
if accountName == "" {
|
||||
return nil, fmt.Errorf("missing AZURE_STORAGE_ACCOUNT_NAME environment variable when AZURE_USE_DEFAULT_CREDENTIAL=true is set; " +
|
||||
"see https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables")
|
||||
}
|
||||
|
||||
serviceURL := fs.getServiceURL(accountName)
|
||||
return service.NewClient(serviceURL, creds, nil)
|
||||
default:
|
||||
return nil, fmt.Errorf(
|
||||
`failed to detect credentials for AZBlob.
|
||||
Ensure that one of the options is set: connection string at %q; shared key at %q and %q; account name at %q and set %q to "true"`,
|
||||
envStorageAccCs,
|
||||
envStorageAcctName,
|
||||
envStorageAccKey,
|
||||
envStorageAcctName,
|
||||
envStorageDefault,
|
||||
)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to detect credentials for AZBlob; ensure that one of the options listed at " +
|
||||
"https://docs.victoriametrics.com/vmbackup/#providing-credentials-via-env-variables is set")
|
||||
}
|
||||
|
||||
func (fs *FS) env(name string) string {
|
||||
if fs.envLookupFunc != nil {
|
||||
v, _ := fs.envLookupFunc(name)
|
||||
return v
|
||||
}
|
||||
v, _ := envtemplate.LookupEnv(name)
|
||||
return v
|
||||
}
|
||||
|
||||
func (fs *FS) getServiceURL(accountName string) string {
|
||||
domain := "blob.core.windows.net"
|
||||
storageDomain := fs.env("AZURE_STORAGE_DOMAIN")
|
||||
if storageDomain != "" {
|
||||
logger.Infof("overriding default Azure blob domain with AZURE_STORAGE_DOMAIN=%q", storageDomain)
|
||||
domain = storageDomain
|
||||
}
|
||||
return fmt.Sprintf("https://%s.%s/", accountName, domain)
|
||||
}
|
||||
|
||||
// MustStop stops fs.
|
||||
@@ -390,7 +390,7 @@ func (fs *FS) HasFile(filePath string) (bool, error) {
|
||||
_, err := bc.GetProperties(ctx, nil)
|
||||
var azerr *azcore.ResponseError
|
||||
if errors.As(err, &azerr) {
|
||||
if azerr.ErrorCode == storageErrorCodeBlobNotFound {
|
||||
if azerr.ErrorCode == "BlobNotFound" {
|
||||
return false, nil
|
||||
}
|
||||
logger.Errorf("GetProperties(%q) returned %s", bc.URL(), err)
|
||||
@@ -416,26 +416,9 @@ func (fs *FS) ReadFile(filePath string) ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// envLookuper is for looking up environment variables. It is
|
||||
// needed to allow unit tests to provide alternate values since the envtemplate
|
||||
// package uses a singleton to read all environment variables into memory at
|
||||
// init time.
|
||||
type envLookuper func(name string) (string, bool)
|
||||
|
||||
func moreThanOne(vals ...bool) bool {
|
||||
var n int
|
||||
|
||||
for _, v := range vals {
|
||||
if v {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n > 1
|
||||
}
|
||||
|
||||
// cleanDirectory ensures that the directory is properly formatted for Azure
|
||||
// Blob Storage. It removes any leading slashes and ensures that the directory
|
||||
// ends with a trailing slash.
|
||||
// cleanDirectory ensures that the directory is properly formatted for Azure Blob Storage.
|
||||
//
|
||||
// It removes any leading slashes and ensures that the directory ends with a trailing slash.
|
||||
func cleanDirectory(dir string) string {
|
||||
for strings.HasPrefix(dir, "/") {
|
||||
dir = dir[1:]
|
||||
|
||||
@@ -20,42 +20,104 @@ func TestCleanDirectory(t *testing.T) {
|
||||
f("foo", "foo/")
|
||||
}
|
||||
|
||||
func TestFSInit(t *testing.T) {
|
||||
f := func(expErr string, params ...string) {
|
||||
func TestFSInit_Failure(t *testing.T) {
|
||||
f := func(envArgs map[string]string, errStrExpected string) {
|
||||
t.Helper()
|
||||
|
||||
env := make(testEnv)
|
||||
for i := 0; i < len(params); i += 2 {
|
||||
env[params[i]] = params[i+1]
|
||||
fs := &FS{
|
||||
Dir: "foo",
|
||||
}
|
||||
env := testEnv(envArgs)
|
||||
fs.envLookupFunc = env.LookupEnv
|
||||
|
||||
fs := &FS{Dir: "foo"}
|
||||
fs.env = env.LookupEnv
|
||||
err := fs.Init()
|
||||
if err != nil {
|
||||
if expErr == "" {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), expErr) {
|
||||
t.Fatalf("expected error: \n%q, \ngot: \n%v", expErr, err)
|
||||
}
|
||||
return
|
||||
if err == nil {
|
||||
t.Fatalf("expecting non-nil error")
|
||||
}
|
||||
if expErr != "" {
|
||||
t.Fatalf("expected to have an error %q, instead got nil", expErr)
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, errStrExpected) {
|
||||
t.Fatalf("expecting %q in the error %q", errStrExpected, errStr)
|
||||
}
|
||||
}
|
||||
|
||||
f("", envStorageAccCs, "BlobEndpoint=https://test.blob.core.windows.net/;SharedAccessSignature=")
|
||||
f("", envStorageAcctName, "test", envStorageAccKey, "dGVhcG90Cg==")
|
||||
f("", envStorageDefault, "true", envStorageAcctName, "test")
|
||||
f("", envStorageAcctName, "test", envStorageAccKey, "dGVhcG90Cg==", envStorageDomain, "foo.bar")
|
||||
var envArgs map[string]string
|
||||
|
||||
f("failed to detect credentials for AZBlob")
|
||||
f("failed to detect credentials for AZBlob", envStorageAcctName, "test")
|
||||
f("failed to create Shared Key", envStorageAcctName, "", envStorageAccKey, "!")
|
||||
f("connection string is either blank or malformed", envStorageAccCs, "")
|
||||
f("failed to process credentials: only one of", envStorageAccCs, "teapot", envStorageAcctName, "test", envStorageAccKey, "dGVhcG90Cg==")
|
||||
f(envArgs, "failed to detect credentials for AZBlob")
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "test",
|
||||
}
|
||||
f(envArgs, "failed to detect credentials for AZBlob")
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "",
|
||||
"AZURE_STORAGE_ACCOUNT_KEY": "!",
|
||||
}
|
||||
f(envArgs, "missing AZURE_STORAGE_ACCOUNT_NAME")
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "foo",
|
||||
"AZURE_STORAGE_ACCOUNT_KEY": "!",
|
||||
}
|
||||
f(envArgs, "failed to create Shared Key credentials")
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_CONNECTION_STRING": "foobar",
|
||||
}
|
||||
f(envArgs, "connection string is either blank or malformed")
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_CONNECTION_STRING": "teapot",
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "test",
|
||||
"AZURE_STORAGE_ACCOUNT_KEY": "dGVhcG90Cg==",
|
||||
}
|
||||
f(envArgs, "connection string is either blank or malformed")
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_USE_DEFAULT_CREDENTIAL": "true",
|
||||
}
|
||||
f(envArgs, "missing AZURE_STORAGE_ACCOUNT_NAME")
|
||||
}
|
||||
|
||||
func TestFSInit_Success(t *testing.T) {
|
||||
f := func(envArgs map[string]string) {
|
||||
t.Helper()
|
||||
|
||||
fs := &FS{
|
||||
Dir: "foo",
|
||||
}
|
||||
env := testEnv(envArgs)
|
||||
fs.envLookupFunc = env.LookupEnv
|
||||
|
||||
err := fs.Init()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error at fs.Init(): %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
envArgs := map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_CONNECTION_STRING": "BlobEndpoint=https://test.blob.core.windows.net/;SharedAccessSignature=",
|
||||
}
|
||||
f(envArgs)
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "test",
|
||||
"AZURE_STORAGE_ACCOUNT_KEY": "dGVhcG90Cg==",
|
||||
}
|
||||
f(envArgs)
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_USE_DEFAULT_CREDENTIAL": "true",
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "test",
|
||||
}
|
||||
f(envArgs)
|
||||
|
||||
envArgs = map[string]string{
|
||||
"AZURE_STORAGE_ACCOUNT_NAME": "test",
|
||||
"AZURE_STORAGE_ACCOUNT_KEY": "dGVhcG90Cg==",
|
||||
"AZURE_STORAGE_DOMAIN": "foo.bar",
|
||||
}
|
||||
f(envArgs)
|
||||
}
|
||||
|
||||
type testEnv map[string]string
|
||||
|
||||
@@ -20,14 +20,16 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
"github.com/klauspost/compress/gzhttp"
|
||||
"github.com/valyala/fastrand"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/appmetrics"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/netutil"
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
"github.com/klauspost/compress/gzhttp"
|
||||
"github.com/valyala/fastrand"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -533,7 +535,7 @@ func GetQuotedRemoteAddr(r *http.Request) string {
|
||||
remoteAddr += ", X-Forwarded-For: " + addr
|
||||
}
|
||||
// quote remoteAddr and X-Forwarded-For, since they may contain untrusted input
|
||||
return strconv.Quote(remoteAddr)
|
||||
return stringsutil.JSONString(remoteAddr)
|
||||
}
|
||||
|
||||
type responseWriterWithAbort struct {
|
||||
|
||||
@@ -673,7 +673,7 @@ func SplitMetricNameToTokens(name string) []string {
|
||||
var nonAlphaNumChars = regexp.MustCompile(`[^a-zA-Z0-9]`)
|
||||
|
||||
var labelNameSanitizer = bytesutil.NewFastStringTransformer(func(s string) string {
|
||||
return unsupportedLabelNameChars.ReplaceAllString(s, "_")
|
||||
return unsupportedLabelNameChars.ReplaceAllLiteralString(s, "_")
|
||||
})
|
||||
|
||||
var unsupportedLabelNameChars = regexp.MustCompile(`[^a-zA-Z0-9_]`)
|
||||
@@ -686,7 +686,7 @@ func SanitizeMetricName(value string) string {
|
||||
}
|
||||
|
||||
var metricNameSanitizer = bytesutil.NewFastStringTransformer(func(s string) string {
|
||||
return unsupportedMetricNameChars.ReplaceAllString(s, "_")
|
||||
return unsupportedMetricNameChars.ReplaceAllLiteralString(s, "_")
|
||||
})
|
||||
|
||||
var unsupportedMetricNameChars = regexp.MustCompile(`[^a-zA-Z0-9_:]`)
|
||||
|
||||
@@ -3,7 +3,6 @@ package promscrape
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/gce"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/proxy"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
func TestMergeLabels(t *testing.T) {
|
||||
@@ -432,7 +432,7 @@ scrape_configs:
|
||||
|
||||
// String returns human-readable representation for sw.
|
||||
func (sw *ScrapeWork) String() string {
|
||||
return strconv.Quote(sw.key())
|
||||
return stringsutil.JSONString(sw.key())
|
||||
}
|
||||
|
||||
func TestGetFileSDScrapeWorkSuccess(t *testing.T) {
|
||||
|
||||
@@ -20,7 +20,7 @@ func SanitizeLabelName(name string) string {
|
||||
}
|
||||
|
||||
var labelNamesSanitizer = bytesutil.NewFastStringTransformer(func(s string) string {
|
||||
return invalidLabelCharRE.ReplaceAllString(s, "_")
|
||||
return invalidLabelCharRE.ReplaceAllLiteralString(s, "_")
|
||||
})
|
||||
|
||||
var invalidLabelCharRE = regexp.MustCompile(`[^a-zA-Z0-9_]`)
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
var maxDroppedTargets = flag.Int("promscrape.maxDroppedTargets", 10000, "The maximum number of droppedTargets to show at /api/v1/targets page. "+
|
||||
@@ -261,21 +262,21 @@ func (tsm *targetStatusMap) WriteActiveTargetsJSON(w io.Writer) {
|
||||
writeLabelsJSON(w, ts.sw.Config.OriginalLabels)
|
||||
fmt.Fprintf(w, `,"labels":`)
|
||||
writeLabelsJSON(w, ts.sw.Config.Labels)
|
||||
fmt.Fprintf(w, `,"scrapePool":%q`, ts.sw.Config.Job())
|
||||
fmt.Fprintf(w, `,"scrapeUrl":%q`, ts.sw.Config.ScrapeURL)
|
||||
fmt.Fprintf(w, `,"scrapePool":%s`, stringsutil.JSONString(ts.sw.Config.Job()))
|
||||
fmt.Fprintf(w, `,"scrapeUrl":%s`, stringsutil.JSONString(ts.sw.Config.ScrapeURL))
|
||||
errMsg := ""
|
||||
if ts.err != nil {
|
||||
errMsg = ts.err.Error()
|
||||
}
|
||||
fmt.Fprintf(w, `,"lastError":%q`, errMsg)
|
||||
fmt.Fprintf(w, `,"lastScrape":%q`, time.Unix(ts.scrapeTime/1000, (ts.scrapeTime%1000)*1e6).Format(time.RFC3339Nano))
|
||||
fmt.Fprintf(w, `,"lastError":%s`, stringsutil.JSONString(errMsg))
|
||||
fmt.Fprintf(w, `,"lastScrape":"%s"`, time.Unix(ts.scrapeTime/1000, (ts.scrapeTime%1000)*1e6).Format(time.RFC3339Nano))
|
||||
fmt.Fprintf(w, `,"lastScrapeDuration":%g`, (time.Millisecond * time.Duration(ts.scrapeDuration)).Seconds())
|
||||
fmt.Fprintf(w, `,"lastSamplesScraped":%d`, ts.samplesScraped)
|
||||
state := "up"
|
||||
if !ts.up {
|
||||
state = "down"
|
||||
}
|
||||
fmt.Fprintf(w, `,"health":%q}`, state)
|
||||
fmt.Fprintf(w, `,"health":%s}`, stringsutil.JSONString(state))
|
||||
if i+1 < len(tss) {
|
||||
fmt.Fprintf(w, `,`)
|
||||
}
|
||||
@@ -287,7 +288,7 @@ func writeLabelsJSON(w io.Writer, labels *promutils.Labels) {
|
||||
fmt.Fprintf(w, `{`)
|
||||
labelsList := labels.GetLabels()
|
||||
for i, label := range labelsList {
|
||||
fmt.Fprintf(w, "%q:%q", label.Name, label.Value)
|
||||
fmt.Fprintf(w, "%s:%s", stringsutil.JSONString(label.Name), stringsutil.JSONString(label.Value))
|
||||
if i+1 < len(labelsList) {
|
||||
fmt.Fprintf(w, `,`)
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ func SanitizeName(name string) string {
|
||||
}
|
||||
|
||||
var namesSanitizer = bytesutil.NewFastStringTransformer(func(s string) string {
|
||||
s = unsupportedDatadogChars.ReplaceAllString(s, "_")
|
||||
s = multiUnderscores.ReplaceAllString(s, "_")
|
||||
s = underscoresWithDots.ReplaceAllString(s, ".")
|
||||
s = unsupportedDatadogChars.ReplaceAllLiteralString(s, "_")
|
||||
s = multiUnderscores.ReplaceAllLiteralString(s, "_")
|
||||
s = underscoresWithDots.ReplaceAllLiteralString(s, ".")
|
||||
return s
|
||||
})
|
||||
|
||||
|
||||
@@ -81,12 +81,12 @@ func (r *Row) UnmarshalMetricAndTags(s string, tagsPool []Tag) ([]Tag, error) {
|
||||
tags := tagsPool[tagsStart:]
|
||||
r.Tags = tags[:len(tags):len(tags)]
|
||||
}
|
||||
if len(r.Metric) == 0 {
|
||||
return tagsPool, fmt.Errorf("metric cannot be empty")
|
||||
}
|
||||
if *sanitizeMetricName {
|
||||
r.Metric = sanitizer.Transform(r.Metric)
|
||||
}
|
||||
if len(r.Metric) == 0 {
|
||||
return tagsPool, fmt.Errorf("metric cannot be empty")
|
||||
}
|
||||
return tagsPool, nil
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) {
|
||||
}
|
||||
v, err := fastfloat.Parse(valueStr)
|
||||
if err != nil {
|
||||
return tagsPool, fmt.Errorf("cannot unmarshal value from %q: %w; original line: %q", valueStr, err, sOrig)
|
||||
return tagsPool, fmt.Errorf("cannot unmarshal metric value from %q: %w; original line: %q", valueStr, err, sOrig)
|
||||
}
|
||||
r.Value = v
|
||||
return tagsPool, nil
|
||||
@@ -213,9 +213,6 @@ func (t *Tag) reset() {
|
||||
|
||||
func (t *Tag) unmarshal(s string) {
|
||||
t.reset()
|
||||
if *sanitizeMetricName {
|
||||
s = sanitizer.Transform(s)
|
||||
}
|
||||
n := strings.IndexByte(s, '=')
|
||||
if n < 0 {
|
||||
// Empty tag value.
|
||||
@@ -226,6 +223,9 @@ func (t *Tag) unmarshal(s string) {
|
||||
t.Key = s[:n]
|
||||
t.Value = s[n+1:]
|
||||
}
|
||||
if *sanitizeMetricName {
|
||||
t.Key = sanitizer.Transform(t.Key)
|
||||
}
|
||||
}
|
||||
|
||||
func stripTrailingWhitespace(s string) string {
|
||||
@@ -257,15 +257,13 @@ func stripLeadingWhitespace(s string) string {
|
||||
|
||||
var sanitizer = bytesutil.NewFastStringTransformer(func(s string) string {
|
||||
// Apply rule to drop some chars to preserve backwards compatibility
|
||||
s = dropChars.Replace(s)
|
||||
s = repeatedDots.ReplaceAllLiteralString(s, ".")
|
||||
|
||||
// Replace any remaining illegal chars
|
||||
return allowedChars.ReplaceAllLiteralString(s, "_")
|
||||
})
|
||||
|
||||
var (
|
||||
dropChars = strings.NewReplacer(
|
||||
`\`, "",
|
||||
"..", ".",
|
||||
)
|
||||
allowedChars = regexp.MustCompile(`[^a-zA-Z0-9:._=\p{L}]`)
|
||||
repeatedDots = regexp.MustCompile(`[.]+`)
|
||||
allowedChars = regexp.MustCompile(`[^a-zA-Z0-9:_.]`)
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnmarshalMetricAndTagsFailure(t *testing.T) {
|
||||
func TestUnmarshalMetricAndTags_Failure(t *testing.T) {
|
||||
f := func(s string) {
|
||||
t.Helper()
|
||||
var r Row
|
||||
@@ -18,9 +18,7 @@ func TestUnmarshalMetricAndTagsFailure(t *testing.T) {
|
||||
f(";foo=bar")
|
||||
}
|
||||
|
||||
func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
sanitizeFlagValue := *sanitizeMetricName
|
||||
*sanitizeMetricName = true
|
||||
func TestUnmarshalMetricAndTags_Success(t *testing.T) {
|
||||
f := func(s string, rExpected *Row) {
|
||||
t.Helper()
|
||||
var r Row
|
||||
@@ -33,10 +31,10 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
}
|
||||
}
|
||||
f(" ", &Row{
|
||||
Metric: "_",
|
||||
Metric: " ",
|
||||
})
|
||||
f("foo ;bar=baz", &Row{
|
||||
Metric: "foo_",
|
||||
Metric: "foo ",
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "bar",
|
||||
@@ -45,7 +43,7 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
},
|
||||
})
|
||||
f("f oo;bar=baz", &Row{
|
||||
Metric: "f_oo",
|
||||
Metric: "f oo",
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "bar",
|
||||
@@ -58,7 +56,7 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "bar",
|
||||
Value: "baz___",
|
||||
Value: "baz ",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -67,7 +65,7 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "bar",
|
||||
Value: "_baz",
|
||||
Value: " baz",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -76,7 +74,7 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "bar",
|
||||
Value: "b_az",
|
||||
Value: "b az",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -84,7 +82,7 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
Metric: "foo",
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "b_ar",
|
||||
Key: "b ar",
|
||||
Value: "baz",
|
||||
},
|
||||
},
|
||||
@@ -105,25 +103,9 @@ func TestUnmarshalMetricAndTagsSuccess(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
f("foo..bar;bar=123;baz=aa=bb", &Row{
|
||||
Metric: "foo.bar",
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "bar",
|
||||
Value: "123",
|
||||
},
|
||||
{
|
||||
Key: "baz",
|
||||
Value: "aa=bb",
|
||||
},
|
||||
},
|
||||
})
|
||||
*sanitizeMetricName = sanitizeFlagValue
|
||||
}
|
||||
|
||||
func TestRowsUnmarshalFailure(t *testing.T) {
|
||||
sanitizeFlagValue := *sanitizeMetricName
|
||||
*sanitizeMetricName = true
|
||||
func TestRowsUnmarshal_Failure(t *testing.T) {
|
||||
f := func(s string) {
|
||||
t.Helper()
|
||||
var rows Rows
|
||||
@@ -147,12 +129,51 @@ func TestRowsUnmarshalFailure(t *testing.T) {
|
||||
|
||||
// invalid timestamp
|
||||
f("aa 123 bar")
|
||||
*sanitizeMetricName = sanitizeFlagValue
|
||||
}
|
||||
|
||||
func TestRowsUnmarshalSuccess(t *testing.T) {
|
||||
sanitizeFlagValue := *sanitizeMetricName
|
||||
*sanitizeMetricName = true
|
||||
func TestRowsUnmarshal_SanitizeMetricNamesSuccess(t *testing.T) {
|
||||
f := func(s string, rowsExpected *Rows) {
|
||||
t.Helper()
|
||||
|
||||
sanitizeMetricNameOrig := *sanitizeMetricName
|
||||
*sanitizeMetricName = true
|
||||
defer func() {
|
||||
*sanitizeMetricName = sanitizeMetricNameOrig
|
||||
}()
|
||||
|
||||
var rows Rows
|
||||
rows.Unmarshal(s)
|
||||
if !reflect.DeepEqual(rows.Rows, rowsExpected.Rows) {
|
||||
t.Fatalf("unexpected rows;\ngot\n%+v;\nwant\n%+v", rows.Rows, rowsExpected.Rows)
|
||||
}
|
||||
}
|
||||
|
||||
// Only metric name.
|
||||
f(`foo...b..a.r\a--baz 123`, &Rows{
|
||||
Rows: []Row{{
|
||||
Metric: `foo.b.a.r_a__baz`,
|
||||
Value: 123,
|
||||
}},
|
||||
})
|
||||
|
||||
// Metric name with tags.
|
||||
// Tag values shouldn't be sanitized.
|
||||
f(`s a;ta g..1=a-b..c;tag2 123 456`, &Rows{
|
||||
Rows: []Row{{
|
||||
Metric: `s_a`,
|
||||
Value: 123,
|
||||
Timestamp: 456,
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "ta_g.1",
|
||||
Value: "a-b..c",
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestRowsUnmarshal_Success(t *testing.T) {
|
||||
f := func(s string, rowsExpected *Rows) {
|
||||
t.Helper()
|
||||
var rows Rows
|
||||
@@ -205,17 +226,17 @@ func TestRowsUnmarshalSuccess(t *testing.T) {
|
||||
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3102
|
||||
f("s a;ta g1=aaa1;tag2=bb b2;tag3 1 23", &Rows{
|
||||
Rows: []Row{{
|
||||
Metric: "s_a",
|
||||
Metric: "s a",
|
||||
Value: 1,
|
||||
Timestamp: 23,
|
||||
Tags: []Tag{
|
||||
{
|
||||
Key: "ta_g1",
|
||||
Key: "ta g1",
|
||||
Value: "aaa1",
|
||||
},
|
||||
{
|
||||
Key: "tag2",
|
||||
Value: "bb_b2",
|
||||
Value: "bb b2",
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -400,5 +421,4 @@ func TestRowsUnmarshalSuccess(t *testing.T) {
|
||||
Timestamp: 1789,
|
||||
}},
|
||||
})
|
||||
*sanitizeMetricName = sanitizeFlagValue
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
// WriteSuccessResponse writes success response for AWS Firehose request.
|
||||
@@ -17,7 +19,7 @@ func WriteSuccessResponse(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
body := fmt.Sprintf(`{"requestId":%q,"timestamp":%d}`, requestID, time.Now().UnixMilli())
|
||||
body := fmt.Sprintf(`{"requestId":%s,"timestamp":%d}`, stringsutil.JSONString(requestID), time.Now().UnixMilli())
|
||||
|
||||
h := w.Header()
|
||||
h.Set("Content-Type", "application/json")
|
||||
|
||||
@@ -221,7 +221,7 @@ func areEqualTracesSkipDuration(s1, s2 string) bool {
|
||||
}
|
||||
|
||||
func zeroDurationsInTrace(s string) string {
|
||||
return skipDurationRe.ReplaceAllString(s, " 0ms: ")
|
||||
return skipDurationRe.ReplaceAllLiteralString(s, " 0ms: ")
|
||||
}
|
||||
|
||||
var skipDurationRe = regexp.MustCompile(" [0-9.]+ms: ")
|
||||
@@ -233,7 +233,7 @@ func areEqualJSONTracesSkipDuration(s1, s2 string) bool {
|
||||
}
|
||||
|
||||
func zeroJSONDurationsInTrace(s string) string {
|
||||
return skipJSONDurationRe.ReplaceAllString(s, `"duration_msec":0`)
|
||||
return skipJSONDurationRe.ReplaceAllLiteralString(s, `"duration_msec":0`)
|
||||
}
|
||||
|
||||
var skipJSONDurationRe = regexp.MustCompile(`"duration_msec":[0-9.]+`)
|
||||
|
||||
@@ -1467,9 +1467,7 @@ func TestIndexDBRepopulateAfterRotation(t *testing.T) {
|
||||
timeMin := currentDayTimestamp - 24*3600*1000
|
||||
timeMax := currentDayTimestamp + 24*3600*1000
|
||||
mrs := testGenerateMetricRows(r, metricRowsN, timeMin, timeMax)
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
t.Fatalf("unexpected error when adding mrs: %s", err)
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
s.DebugFlush()
|
||||
|
||||
// verify the storage contains rows.
|
||||
@@ -1521,9 +1519,7 @@ func TestIndexDBRepopulateAfterRotation(t *testing.T) {
|
||||
}
|
||||
|
||||
// Re-insert rows again and verify that all the entries belong to new generation
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
t.Fatalf("unexpected error when adding mrs: %s", err)
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
s.DebugFlush()
|
||||
|
||||
for _, mr := range mrs {
|
||||
|
||||
@@ -104,15 +104,11 @@ func TestSearch(t *testing.T) {
|
||||
|
||||
blockRowsCount++
|
||||
if blockRowsCount == rowsPerBlock {
|
||||
if err := st.AddRows(mrs[i-blockRowsCount+1:i+1], defaultPrecisionBits); err != nil {
|
||||
t.Fatalf("cannot add rows %d-%d: %s", i-blockRowsCount+1, i+1, err)
|
||||
}
|
||||
st.AddRows(mrs[i-blockRowsCount+1:i+1], defaultPrecisionBits)
|
||||
blockRowsCount = 0
|
||||
}
|
||||
}
|
||||
if err := st.AddRows(mrs[rowsCount-blockRowsCount:], defaultPrecisionBits); err != nil {
|
||||
t.Fatalf("cannot add rows %v-%v: %s", rowsCount-blockRowsCount, rowsCount, err)
|
||||
}
|
||||
st.AddRows(mrs[rowsCount-blockRowsCount:], defaultPrecisionBits)
|
||||
endTimestamp := mrs[len(mrs)-1].Timestamp
|
||||
|
||||
// Re-open the storage in order to flush all the pending cached data.
|
||||
|
||||
@@ -1612,13 +1612,12 @@ var rowsAddedTotal atomic.Uint64
|
||||
//
|
||||
// The caller should limit the number of concurrent AddRows calls to the number
|
||||
// of available CPU cores in order to limit memory usage.
|
||||
func (s *Storage) AddRows(mrs []MetricRow, precisionBits uint8) error {
|
||||
func (s *Storage) AddRows(mrs []MetricRow, precisionBits uint8) {
|
||||
if len(mrs) == 0 {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// Add rows to the storage in blocks with limited size in order to reduce memory usage.
|
||||
var firstErr error
|
||||
ic := getMetricRowsInsertCtx()
|
||||
maxBlockLen := len(ic.rrs)
|
||||
for len(mrs) > 0 {
|
||||
@@ -1629,17 +1628,10 @@ func (s *Storage) AddRows(mrs []MetricRow, precisionBits uint8) error {
|
||||
} else {
|
||||
mrs = nil
|
||||
}
|
||||
if err := s.add(ic.rrs, ic.tmpMrs, mrsBlock, precisionBits); err != nil {
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
s.add(ic.rrs, ic.tmpMrs, mrsBlock, precisionBits)
|
||||
rowsAddedTotal.Add(uint64(len(mrsBlock)))
|
||||
}
|
||||
putMetricRowsInsertCtx(ic)
|
||||
|
||||
return firstErr
|
||||
}
|
||||
|
||||
type metricRowsInsertCtx struct {
|
||||
@@ -1778,7 +1770,7 @@ func (s *Storage) RegisterMetricNames(qt *querytracer.Tracer, mrs []MetricRow) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Storage) add(rows []rawRow, dstMrs []*MetricRow, mrs []MetricRow, precisionBits uint8) error {
|
||||
func (s *Storage) add(rows []rawRow, dstMrs []*MetricRow, mrs []MetricRow, precisionBits uint8) {
|
||||
idb := s.idb()
|
||||
generation := idb.generation
|
||||
is := idb.getIndexSearch(noDeadline)
|
||||
@@ -1802,7 +1794,7 @@ func (s *Storage) add(rows []rawRow, dstMrs []*MetricRow, mrs []MetricRow, preci
|
||||
|
||||
var genTSID generationTSID
|
||||
|
||||
// Return only the first error, since it has no sense in returning all errors.
|
||||
// Log only the first error, since it has no sense in logging all errors.
|
||||
var firstWarn error
|
||||
|
||||
j := 0
|
||||
@@ -1968,23 +1960,20 @@ func (s *Storage) add(rows []rawRow, dstMrs []*MetricRow, mrs []MetricRow, preci
|
||||
|
||||
if err := s.prefillNextIndexDB(rows, dstMrs); err != nil {
|
||||
if firstWarn == nil {
|
||||
firstWarn = err
|
||||
firstWarn = fmt.Errorf("cannot prefill next indexdb: %w", err)
|
||||
}
|
||||
}
|
||||
if err := s.updatePerDateData(rows, dstMrs); err != nil {
|
||||
if firstWarn == nil {
|
||||
firstWarn = fmt.Errorf("cannot not update per-day index: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if firstWarn != nil {
|
||||
storageAddRowsLogger.Warnf("warn occurred during rows addition: %s", firstWarn)
|
||||
}
|
||||
|
||||
err := s.updatePerDateData(rows, dstMrs)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("cannot update per-date data: %w", err)
|
||||
} else {
|
||||
s.tb.MustAddRows(rows)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred during rows addition: %w", err)
|
||||
}
|
||||
return nil
|
||||
s.tb.MustAddRows(rows)
|
||||
}
|
||||
|
||||
var storageAddRowsLogger = logger.WithThrottler("storageAddRows", 5*time.Second)
|
||||
|
||||
@@ -2,12 +2,12 @@ package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/decimal"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/uint64set"
|
||||
)
|
||||
|
||||
@@ -570,12 +571,7 @@ func testStorageRandTimestamps(s *Storage) error {
|
||||
}
|
||||
mrs = append(mrs, mr)
|
||||
}
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, "too big timestamp") && !strings.Contains(errStr, "too small timestamp") {
|
||||
return fmt.Errorf("unexpected error when adding mrs: %w", err)
|
||||
}
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
}
|
||||
|
||||
// Verify the storage contains rows.
|
||||
@@ -691,9 +687,7 @@ func testStorageDeleteSeries(s *Storage, workerNum int) error {
|
||||
}
|
||||
mrs = append(mrs, mr)
|
||||
}
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
return fmt.Errorf("unexpected error when adding mrs: %w", err)
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
}
|
||||
s.DebugFlush()
|
||||
|
||||
@@ -1031,9 +1025,7 @@ func testStorageAddRows(rng *rand.Rand, s *Storage) error {
|
||||
minTimestamp := maxTimestamp - s.retentionMsecs + 3600*1000
|
||||
for i := 0; i < addsCount; i++ {
|
||||
mrs := testGenerateMetricRows(rng, rowsPerAdd, minTimestamp, maxTimestamp)
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
return fmt.Errorf("unexpected error when adding mrs: %w", err)
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
}
|
||||
|
||||
// Verify the storage contains rows.
|
||||
@@ -1172,9 +1164,7 @@ func testStorageAddMetrics(s *Storage, workerNum int) error {
|
||||
Timestamp: timestamp,
|
||||
Value: value,
|
||||
}
|
||||
if err := s.AddRows([]MetricRow{mr}, defaultPrecisionBits); err != nil {
|
||||
return fmt.Errorf("unexpected error when adding mrs: %w", err)
|
||||
}
|
||||
s.AddRows([]MetricRow{mr}, defaultPrecisionBits)
|
||||
}
|
||||
|
||||
// Verify the storage contains rows.
|
||||
@@ -1198,9 +1188,7 @@ func TestStorageDeleteStaleSnapshots(t *testing.T) {
|
||||
minTimestamp := maxTimestamp - s.retentionMsecs
|
||||
for i := 0; i < addsCount; i++ {
|
||||
mrs := testGenerateMetricRows(rng, rowsPerAdd, minTimestamp, maxTimestamp)
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
t.Fatalf("unexpected error when adding mrs: %s", err)
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
}
|
||||
// Try creating a snapshot from the storage.
|
||||
snapshotName, err := s.CreateSnapshot()
|
||||
@@ -1268,9 +1256,7 @@ func TestStorageSeriesAreNotCreatedOnStaleMarkers(t *testing.T) {
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
mrs := testGenerateMetricRows(rng, 20, tr.MinTimestamp, tr.MaxTimestamp)
|
||||
// populate storage with some rows
|
||||
if err := s.AddRows(mrs[:10], defaultPrecisionBits); err != nil {
|
||||
t.Fatal("error when adding mrs: %w", err)
|
||||
}
|
||||
s.AddRows(mrs[:10], defaultPrecisionBits)
|
||||
s.DebugFlush()
|
||||
|
||||
// verify ingested rows are searchable
|
||||
@@ -1289,9 +1275,7 @@ func TestStorageSeriesAreNotCreatedOnStaleMarkers(t *testing.T) {
|
||||
for i := 0; i < len(mrs); i = i + 2 {
|
||||
mrs[i].Value = decimal.StaleNaN
|
||||
}
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
t.Fatal("error when adding mrs: %w", err)
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
s.DebugFlush()
|
||||
|
||||
// verify that rows marked as stale aren't searchable
|
||||
@@ -1302,3 +1286,166 @@ func TestStorageSeriesAreNotCreatedOnStaleMarkers(t *testing.T) {
|
||||
t.Fatalf("cannot remove %q: %s", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
// testRemoveAll removes all storage data produced by a test if the test hasn't
|
||||
// failed. For this to work, the storage must use t.Name() as the base dir in
|
||||
// its data path.
|
||||
//
|
||||
// In case of failure, the data is kept for further debugging.
|
||||
func testRemoveAll(t *testing.T) {
|
||||
defer func() {
|
||||
if !t.Failed() {
|
||||
fs.MustRemoveAll(t.Name())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func TestStorageRowsNotAdded(t *testing.T) {
|
||||
defer testRemoveAll(t)
|
||||
|
||||
type options struct {
|
||||
name string
|
||||
retention time.Duration
|
||||
mrs []MetricRow
|
||||
tr TimeRange
|
||||
}
|
||||
f := func(opts *options) {
|
||||
t.Helper()
|
||||
|
||||
var gotMetrics Metrics
|
||||
path := fmt.Sprintf("%s/%s", t.Name(), opts.name)
|
||||
s := MustOpenStorage(path, opts.retention, 0, 0)
|
||||
defer s.MustClose()
|
||||
s.AddRows(opts.mrs, defaultPrecisionBits)
|
||||
s.DebugFlush()
|
||||
s.UpdateMetrics(&gotMetrics)
|
||||
|
||||
got := testCountAllMetricNames(s, opts.tr)
|
||||
if got != 0 {
|
||||
t.Fatalf("unexpected metric name count: got %d, want 0", got)
|
||||
}
|
||||
}
|
||||
|
||||
const numRows = 1000
|
||||
var (
|
||||
rng = rand.New(rand.NewSource(1))
|
||||
retention time.Duration
|
||||
minTimestamp int64
|
||||
maxTimestamp int64
|
||||
mrs []MetricRow
|
||||
)
|
||||
|
||||
minTimestamp = -1000
|
||||
maxTimestamp = -1
|
||||
f(&options{
|
||||
name: "NegativeTimestamps",
|
||||
retention: retentionMax,
|
||||
mrs: testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp),
|
||||
tr: TimeRange{minTimestamp, maxTimestamp},
|
||||
})
|
||||
|
||||
retention = 48 * time.Hour
|
||||
minTimestamp = time.Now().Add(-retention - time.Hour).UnixMilli()
|
||||
maxTimestamp = minTimestamp + 1000
|
||||
f(&options{
|
||||
name: "TooSmallTimestamps",
|
||||
retention: retention,
|
||||
mrs: testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp),
|
||||
tr: TimeRange{minTimestamp, maxTimestamp},
|
||||
})
|
||||
|
||||
retention = 48 * time.Hour
|
||||
minTimestamp = time.Now().Add(7 * 24 * time.Hour).UnixMilli()
|
||||
maxTimestamp = minTimestamp + 1000
|
||||
f(&options{
|
||||
name: "TooBigTimestamps",
|
||||
retention: retention,
|
||||
mrs: testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp),
|
||||
tr: TimeRange{minTimestamp, maxTimestamp},
|
||||
})
|
||||
|
||||
minTimestamp = time.Now().UnixMilli()
|
||||
maxTimestamp = minTimestamp + 1000
|
||||
mrs = testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp)
|
||||
for i := range numRows {
|
||||
mrs[i].Value = math.NaN()
|
||||
}
|
||||
f(&options{
|
||||
name: "NaN",
|
||||
mrs: mrs,
|
||||
tr: TimeRange{minTimestamp, maxTimestamp},
|
||||
})
|
||||
|
||||
minTimestamp = time.Now().UnixMilli()
|
||||
maxTimestamp = minTimestamp + 1000
|
||||
mrs = testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp)
|
||||
for i := range numRows {
|
||||
mrs[i].Value = decimal.StaleNaN
|
||||
}
|
||||
f(&options{
|
||||
name: "StaleNaN",
|
||||
mrs: mrs,
|
||||
tr: TimeRange{minTimestamp, maxTimestamp},
|
||||
})
|
||||
|
||||
minTimestamp = time.Now().UnixMilli()
|
||||
maxTimestamp = minTimestamp + 1000
|
||||
mrs = testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp)
|
||||
for i := range numRows {
|
||||
mrs[i].MetricNameRaw = []byte("garbage")
|
||||
}
|
||||
f(&options{
|
||||
name: "InvalidMetricNameRaw",
|
||||
mrs: mrs,
|
||||
tr: TimeRange{minTimestamp, maxTimestamp},
|
||||
})
|
||||
}
|
||||
|
||||
func TestStorageRowsNotAdded_SeriesLimitExceeded(t *testing.T) {
|
||||
defer testRemoveAll(t)
|
||||
|
||||
f := func(name string, maxHourlySeries int, maxDailySeries int) {
|
||||
t.Helper()
|
||||
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
numRows := uint64(1000)
|
||||
minTimestamp := time.Now().UnixMilli()
|
||||
maxTimestamp := minTimestamp + 1000
|
||||
mrs := testGenerateMetricRows(rng, numRows, minTimestamp, maxTimestamp)
|
||||
|
||||
var gotMetrics Metrics
|
||||
path := fmt.Sprintf("%s/%s", t.Name(), name)
|
||||
s := MustOpenStorage(path, 0, maxHourlySeries, maxDailySeries)
|
||||
defer s.MustClose()
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
s.DebugFlush()
|
||||
s.UpdateMetrics(&gotMetrics)
|
||||
|
||||
want := numRows - (gotMetrics.HourlySeriesLimitRowsDropped + gotMetrics.DailySeriesLimitRowsDropped)
|
||||
if got := testCountAllMetricNames(s, TimeRange{minTimestamp, maxTimestamp}); uint64(got) != want {
|
||||
t.Fatalf("unexpected metric name count: %d, want %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
maxHourlySeries := 1
|
||||
maxDailySeries := 0 // No limit
|
||||
f("HourlyLimitExceeded", maxHourlySeries, maxDailySeries)
|
||||
|
||||
maxHourlySeries = 0 // No limit
|
||||
maxDailySeries = 1
|
||||
f("DailyLimitExceeded", maxHourlySeries, maxDailySeries)
|
||||
}
|
||||
|
||||
// testCountAllMetricNames is a test helper function that counts the names of
|
||||
// all time series within the given time range.
|
||||
func testCountAllMetricNames(s *Storage, tr TimeRange) int {
|
||||
tfsAll := NewTagFilters()
|
||||
if err := tfsAll.Add([]byte("__name__"), []byte(".*"), false, true); err != nil {
|
||||
panic(fmt.Sprintf("unexpected error in TagFilters.Add: %v", err))
|
||||
}
|
||||
names, err := s.SearchMetricNames(nil, []*TagFilters{tfsAll}, tr, 1e9, noDeadline)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("SeachMetricNames() failed unexpectedly: %v", err))
|
||||
}
|
||||
return len(names)
|
||||
}
|
||||
|
||||
@@ -46,9 +46,7 @@ func benchmarkStorageAddRows(b *testing.B, rowsPerBatch int) {
|
||||
mr.Timestamp = int64(offset + i)
|
||||
mr.Value = float64(offset + i)
|
||||
}
|
||||
if err := s.AddRows(mrs, defaultPrecisionBits); err != nil {
|
||||
panic(fmt.Errorf("cannot add rows to storage: %w", err))
|
||||
}
|
||||
s.AddRows(mrs, defaultPrecisionBits)
|
||||
}
|
||||
})
|
||||
b.StopTimer()
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/valyala/histogram"
|
||||
)
|
||||
|
||||
// quantilesAggrState calculates output=quantiles, e.g. the the given quantiles over the input samples.
|
||||
// quantilesAggrState calculates output=quantiles, e.g. the given quantiles over the input samples.
|
||||
type quantilesAggrState struct {
|
||||
m sync.Map
|
||||
|
||||
|
||||
@@ -135,6 +135,14 @@ type Options struct {
|
||||
//
|
||||
// This option can be overridden individually per each aggregation via ignore_first_intervals option.
|
||||
IgnoreFirstIntervals int
|
||||
|
||||
// KeepInput defines whether to keep all the input samples after the aggregation.
|
||||
// By default, only aggregates samples are dropped, while the remaining samples are written to remote storages write.
|
||||
KeepInput bool
|
||||
|
||||
// DropInput defines whether to drop all the input samples after the aggregation.
|
||||
// By default, only aggregates samples are dropped, while the remaining samples are written to remote storages write.
|
||||
DropInput bool
|
||||
}
|
||||
|
||||
// Config is a configuration for a single stream aggregation.
|
||||
@@ -237,6 +245,10 @@ type Config struct {
|
||||
// OutputRelabelConfigs is an optional relabeling rules, which are applied
|
||||
// on the aggregated output before being sent to remote storage.
|
||||
OutputRelabelConfigs []promrelabel.RelabelConfig `yaml:"output_relabel_configs,omitempty"`
|
||||
|
||||
// KeepInput defines whether to keep all the input samples after the aggregation.
|
||||
// By default, only aggregates samples are dropped, while the remaining samples are written to remote storages write.
|
||||
KeepInput *bool `yaml:"keep_input,omitempty"`
|
||||
}
|
||||
|
||||
// Aggregators aggregates metrics passed to Push and calls pushFunc for aggregated data.
|
||||
@@ -252,6 +264,8 @@ type Aggregators struct {
|
||||
|
||||
// ms contains metrics associated with the Aggregators.
|
||||
ms *metrics.Set
|
||||
|
||||
dropInput bool
|
||||
}
|
||||
|
||||
// FilePath returns path to file with the configuration used for creating the given Aggregators.
|
||||
@@ -291,12 +305,16 @@ func loadFromData(data []byte, filePath string, pushFunc PushFunc, opts *Options
|
||||
}
|
||||
|
||||
metrics.RegisterSet(ms)
|
||||
return &Aggregators{
|
||||
a := &Aggregators{
|
||||
as: as,
|
||||
configData: configData,
|
||||
filePath: filePath,
|
||||
ms: ms,
|
||||
}, nil
|
||||
}
|
||||
if opts != nil {
|
||||
a.dropInput = opts.DropInput
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// IsEnabled returns true if Aggregators has at least one configured aggregator
|
||||
@@ -325,6 +343,19 @@ func (a *Aggregators) MustStop() {
|
||||
a.as = nil
|
||||
}
|
||||
|
||||
// ExpectModifications returns true if Push modifies original timeseries
|
||||
func (a *Aggregators) ExpectModifications() bool {
|
||||
if a == nil {
|
||||
return false
|
||||
}
|
||||
for _, aggr := range a.as {
|
||||
if aggr.keepInput {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if a and b are initialized from identical configs.
|
||||
func (a *Aggregators) Equal(b *Aggregators) bool {
|
||||
if a == nil || b == nil {
|
||||
@@ -333,28 +364,39 @@ func (a *Aggregators) Equal(b *Aggregators) bool {
|
||||
return string(a.configData) == string(b.configData)
|
||||
}
|
||||
|
||||
// Push pushes tss to a.
|
||||
// Push calls PushWithCallback with an empty default callback
|
||||
func (a *Aggregators) Push(tss []prompbmarshal.TimeSeries) []prompbmarshal.TimeSeries {
|
||||
defaultCallback := func(_ []byte) {}
|
||||
return a.PushWithCallback(tss, defaultCallback)
|
||||
}
|
||||
|
||||
// PushWithCallback pushes tss to a.
|
||||
//
|
||||
// Push sets matchIdxs[idx] to 1 if the corresponding tss[idx] was used in aggregations.
|
||||
// PushWithCallback calls callback with matchIdxs, where matchIdx[idx] is set to 1 if the corresponding tss[idx] was used in aggregations.
|
||||
// Otherwise matchIdxs[idx] is set to 0.
|
||||
//
|
||||
// Push returns matchIdxs with len equal to len(tss).
|
||||
// It re-uses the matchIdxs if it has enough capacity to hold len(tss) items.
|
||||
// Otherwise it allocates new matchIdxs.
|
||||
func (a *Aggregators) Push(tss []prompbmarshal.TimeSeries, matchIdxs []byte) []byte {
|
||||
matchIdxs = bytesutil.ResizeNoCopyMayOverallocate(matchIdxs, len(tss))
|
||||
for i := range matchIdxs {
|
||||
matchIdxs[i] = 0
|
||||
}
|
||||
// Push returns modified timeseries.
|
||||
func (a *Aggregators) PushWithCallback(tss []prompbmarshal.TimeSeries, callback func([]byte)) []prompbmarshal.TimeSeries {
|
||||
if a == nil {
|
||||
return matchIdxs
|
||||
return tss
|
||||
}
|
||||
|
||||
matchIdxs := matchIdxsPool.Get()
|
||||
defer matchIdxsPool.Put(matchIdxs)
|
||||
for _, aggr := range a.as {
|
||||
aggr.Push(tss, matchIdxs)
|
||||
matchIdxs.B = bytesutil.ResizeNoCopyMayOverallocate(matchIdxs.B, len(tss))
|
||||
for i := range matchIdxs.B {
|
||||
matchIdxs.B[i] = 0
|
||||
}
|
||||
aggr.Push(tss, matchIdxs.B)
|
||||
if !aggr.keepInput {
|
||||
callback(matchIdxs.B)
|
||||
tss = dropAggregatedSeries(tss, matchIdxs.B)
|
||||
}
|
||||
}
|
||||
|
||||
return matchIdxs
|
||||
if a.dropInput {
|
||||
tss = tss[:0]
|
||||
}
|
||||
return tss
|
||||
}
|
||||
|
||||
// aggregator aggregates input series according to the config passed to NewAggregator
|
||||
@@ -368,6 +410,7 @@ type aggregator struct {
|
||||
|
||||
keepMetricNames bool
|
||||
ignoreOldSamples bool
|
||||
keepInput bool
|
||||
|
||||
by []string
|
||||
without []string
|
||||
@@ -546,6 +589,12 @@ func newAggregator(cfg *Config, path string, pushFunc PushFunc, ms *metrics.Set,
|
||||
}
|
||||
metricLabels := fmt.Sprintf(`name=%q,path=%q,url=%q,position="%d"`, name, path, alias, aggrID)
|
||||
|
||||
// check cfg.KeepInput
|
||||
keepInput := opts.KeepInput
|
||||
if v := cfg.KeepInput; v != nil {
|
||||
keepInput = *v
|
||||
}
|
||||
|
||||
// initialize aggrOutputs
|
||||
if len(cfg.Outputs) == 0 {
|
||||
return nil, fmt.Errorf("`outputs` list must contain at least a single entry from the list %s; "+
|
||||
@@ -585,6 +634,7 @@ func newAggregator(cfg *Config, path string, pushFunc PushFunc, ms *metrics.Set,
|
||||
|
||||
keepMetricNames: keepMetricNames,
|
||||
ignoreOldSamples: ignoreOldSamples,
|
||||
keepInput: keepInput,
|
||||
|
||||
by: by,
|
||||
without: without,
|
||||
@@ -884,7 +934,7 @@ func (a *aggregator) MustStop() {
|
||||
a.wg.Wait()
|
||||
}
|
||||
|
||||
// Push pushes tss to a.
|
||||
// push pushes tss to a.
|
||||
func (a *aggregator) Push(tss []prompbmarshal.TimeSeries, matchIdxs []byte) {
|
||||
ctx := getPushCtx()
|
||||
defer putPushCtx(ctx)
|
||||
@@ -1050,6 +1100,8 @@ func putPushCtx(ctx *pushCtx) {
|
||||
pushCtxPool.Put(ctx)
|
||||
}
|
||||
|
||||
var matchIdxsPool bytesutil.ByteBufferPool
|
||||
|
||||
var pushCtxPool sync.Pool
|
||||
|
||||
func getInputOutputLabels(dstInput, dstOutput, labels []prompbmarshal.Label, by, without []string) ([]prompbmarshal.Label, []prompbmarshal.Label) {
|
||||
@@ -1273,4 +1325,17 @@ func sortAndRemoveDuplicates(a []string) []string {
|
||||
return dst
|
||||
}
|
||||
|
||||
func dropAggregatedSeries(src []prompbmarshal.TimeSeries, matchIdxs []byte) []prompbmarshal.TimeSeries {
|
||||
dst := src[:0]
|
||||
for i, match := range matchIdxs {
|
||||
if match == 1 {
|
||||
continue
|
||||
}
|
||||
dst = append(dst, src[i])
|
||||
}
|
||||
tail := src[len(dst):]
|
||||
clear(tail)
|
||||
return dst
|
||||
}
|
||||
|
||||
var bbPool bytesutil.ByteBufferPool
|
||||
|
||||
@@ -3,7 +3,6 @@ package streamaggr
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -252,7 +251,7 @@ func TestAggregatorsEqual(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAggregatorsSuccess(t *testing.T) {
|
||||
f := func(config, inputMetrics, outputMetricsExpected, matchIdxsStrExpected string) {
|
||||
f := func(config, inputMetrics, outputMetricsExpected string, matchedIdxsExpected int) {
|
||||
t.Helper()
|
||||
|
||||
// Initialize Aggregators
|
||||
@@ -275,16 +274,18 @@ func TestAggregatorsSuccess(t *testing.T) {
|
||||
// Push the inputMetrics to Aggregators
|
||||
offsetMsecs := time.Now().UnixMilli()
|
||||
tssInput := prompbmarshal.MustParsePromMetrics(inputMetrics, offsetMsecs)
|
||||
matchIdxs := a.Push(tssInput, nil)
|
||||
var matchedIdxs int
|
||||
_ = a.PushWithCallback(tssInput, func(idxs []byte) {
|
||||
for _, idx := range idxs {
|
||||
if idx == 1 {
|
||||
matchedIdxs++
|
||||
}
|
||||
}
|
||||
})
|
||||
a.MustStop()
|
||||
|
||||
// Verify matchIdxs equals to matchIdxsExpected
|
||||
matchIdxsStr := ""
|
||||
for _, v := range matchIdxs {
|
||||
matchIdxsStr += strconv.Itoa(int(v))
|
||||
}
|
||||
if matchIdxsStr != matchIdxsStrExpected {
|
||||
t.Fatalf("unexpected matchIdxs;\ngot\n%s\nwant\n%s", matchIdxsStr, matchIdxsStrExpected)
|
||||
if matchedIdxs != matchedIdxsExpected {
|
||||
t.Fatalf("unexpected matchIdxs;\ngot\n%d\nwant\n%d", matchedIdxs, matchedIdxsExpected)
|
||||
}
|
||||
|
||||
// Verify the tssOutput contains the expected metrics
|
||||
@@ -295,9 +296,9 @@ func TestAggregatorsSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
// Empty config
|
||||
f(``, ``, ``, "")
|
||||
f(``, `foo{bar="baz"} 1`, ``, "0")
|
||||
f(``, "foo 1\nbaz 2", ``, "00")
|
||||
f(``, ``, ``, 0)
|
||||
f(``, `foo{bar="baz"} 1`, ``, 0)
|
||||
f(``, "foo 1\nbaz 2", ``, 0)
|
||||
|
||||
// Empty by list - aggregate only by time
|
||||
f(`
|
||||
@@ -321,7 +322,7 @@ foo:1m_last{abc="123"} 8.5
|
||||
foo:1m_last{abc="456",de="fg"} 8
|
||||
foo:1m_sum_samples{abc="123"} 12.5
|
||||
foo:1m_sum_samples{abc="456",de="fg"} 8
|
||||
`, "11111")
|
||||
`, 5)
|
||||
|
||||
// Special case: __name__ in `by` list - this is the same as empty `by` list
|
||||
f(`
|
||||
@@ -339,7 +340,7 @@ bar:1m_sum_samples 5
|
||||
foo:1m_count_samples 3
|
||||
foo:1m_count_series 2
|
||||
foo:1m_sum_samples 20.5
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// Non-empty `by` list with non-existing labels
|
||||
f(`
|
||||
@@ -357,7 +358,7 @@ bar:1m_by_bar_foo_sum_samples 5
|
||||
foo:1m_by_bar_foo_count_samples 3
|
||||
foo:1m_by_bar_foo_count_series 2
|
||||
foo:1m_by_bar_foo_sum_samples 20.5
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// Non-empty `by` list with existing label
|
||||
f(`
|
||||
@@ -378,7 +379,7 @@ foo:1m_by_abc_count_series{abc="123"} 1
|
||||
foo:1m_by_abc_count_series{abc="456"} 1
|
||||
foo:1m_by_abc_sum_samples{abc="123"} 12.5
|
||||
foo:1m_by_abc_sum_samples{abc="456"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// Non-empty `by` list with duplicate existing label
|
||||
f(`
|
||||
@@ -399,7 +400,7 @@ foo:1m_by_abc_count_series{abc="123"} 1
|
||||
foo:1m_by_abc_count_series{abc="456"} 1
|
||||
foo:1m_by_abc_sum_samples{abc="123"} 12.5
|
||||
foo:1m_by_abc_sum_samples{abc="456"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// Non-empty `without` list with non-existing labels
|
||||
f(`
|
||||
@@ -420,7 +421,7 @@ foo:1m_without_foo_count_series{abc="123"} 1
|
||||
foo:1m_without_foo_count_series{abc="456",de="fg"} 1
|
||||
foo:1m_without_foo_sum_samples{abc="123"} 12.5
|
||||
foo:1m_without_foo_sum_samples{abc="456",de="fg"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// Non-empty `without` list with existing labels
|
||||
f(`
|
||||
@@ -441,7 +442,7 @@ foo:1m_without_abc_count_series 1
|
||||
foo:1m_without_abc_count_series{de="fg"} 1
|
||||
foo:1m_without_abc_sum_samples 12.5
|
||||
foo:1m_without_abc_sum_samples{de="fg"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// Special case: __name__ in `without` list
|
||||
f(`
|
||||
@@ -462,7 +463,7 @@ foo{abc="456",de="fg"} 8
|
||||
:1m_sum_samples 5
|
||||
:1m_sum_samples{abc="123"} 12.5
|
||||
:1m_sum_samples{abc="456",de="fg"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// drop some input metrics
|
||||
f(`
|
||||
@@ -480,7 +481,7 @@ foo{abc="456",de="fg"} 8
|
||||
`, `bar:1m_without_abc_count_samples 1
|
||||
bar:1m_without_abc_count_series 1
|
||||
bar:1m_without_abc_sum_samples 5
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// rename output metrics
|
||||
f(`
|
||||
@@ -507,7 +508,7 @@ bar-1m-without-abc-sum-samples 5
|
||||
foo-1m-without-abc-count-samples 2
|
||||
foo-1m-without-abc-count-series 1
|
||||
foo-1m-without-abc-sum-samples 12.5
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// match doesn't match anything
|
||||
f(`
|
||||
@@ -521,7 +522,7 @@ foo{abc="123"} 4
|
||||
bar 5
|
||||
foo{abc="123"} 8.5
|
||||
foo{abc="456",de="fg"} 8
|
||||
`, ``, "0000")
|
||||
`, ``, 0)
|
||||
|
||||
// match matches foo series with non-empty abc label
|
||||
f(`
|
||||
@@ -543,7 +544,7 @@ foo:1m_by_abc_count_series{abc="123"} 1
|
||||
foo:1m_by_abc_count_series{abc="456"} 1
|
||||
foo:1m_by_abc_sum_samples{abc="123"} 12.5
|
||||
foo:1m_by_abc_sum_samples{abc="456"} 8
|
||||
`, "1011")
|
||||
`, 3)
|
||||
|
||||
// total output for non-repeated series
|
||||
f(`
|
||||
@@ -554,7 +555,7 @@ foo 123
|
||||
bar{baz="qwe"} 4.34
|
||||
`, `bar:1m_total{baz="qwe"} 0
|
||||
foo:1m_total 0
|
||||
`, "11")
|
||||
`, 2)
|
||||
|
||||
// total_prometheus output for non-repeated series
|
||||
f(`
|
||||
@@ -565,7 +566,7 @@ foo 123
|
||||
bar{baz="qwe"} 4.34
|
||||
`, `bar:1m_total_prometheus{baz="qwe"} 0
|
||||
foo:1m_total_prometheus 0
|
||||
`, "11")
|
||||
`, 2)
|
||||
|
||||
// total output for repeated series
|
||||
f(`
|
||||
@@ -584,7 +585,7 @@ foo{baz="qwe"} 10
|
||||
bar:1m_total{baz="qwer"} 1
|
||||
foo:1m_total 0
|
||||
foo:1m_total{baz="qwe"} 15
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
|
||||
// total_prometheus output for repeated series
|
||||
f(`
|
||||
@@ -603,7 +604,7 @@ foo{baz="qwe"} 10
|
||||
bar:1m_total_prometheus{baz="qwer"} 1
|
||||
foo:1m_total_prometheus 0
|
||||
foo:1m_total_prometheus{baz="qwe"} 15
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
|
||||
// total output for repeated series with group by __name__
|
||||
f(`
|
||||
@@ -621,7 +622,7 @@ bar{baz="qwer"} 344
|
||||
foo{baz="qwe"} 10
|
||||
`, `bar:1m_total 6.02
|
||||
foo:1m_total 15
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
|
||||
// total_prometheus output for repeated series with group by __name__
|
||||
f(`
|
||||
@@ -639,7 +640,7 @@ bar{baz="qwer"} 344
|
||||
foo{baz="qwe"} 10
|
||||
`, `bar:1m_total_prometheus 6.02
|
||||
foo:1m_total_prometheus 15
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
|
||||
// increase output for non-repeated series
|
||||
f(`
|
||||
@@ -650,7 +651,7 @@ foo 123
|
||||
bar{baz="qwe"} 4.34
|
||||
`, `bar:1m_increase{baz="qwe"} 0
|
||||
foo:1m_increase 0
|
||||
`, "11")
|
||||
`, 2)
|
||||
|
||||
// increase_prometheus output for non-repeated series
|
||||
f(`
|
||||
@@ -661,7 +662,7 @@ foo 123
|
||||
bar{baz="qwe"} 4.34
|
||||
`, `bar:1m_increase_prometheus{baz="qwe"} 0
|
||||
foo:1m_increase_prometheus 0
|
||||
`, "11")
|
||||
`, 2)
|
||||
|
||||
// increase output for repeated series
|
||||
f(`
|
||||
@@ -680,7 +681,7 @@ foo{baz="qwe"} 10
|
||||
bar:1m_increase{baz="qwer"} 1
|
||||
foo:1m_increase 0
|
||||
foo:1m_increase{baz="qwe"} 15
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
|
||||
// increase_prometheus output for repeated series
|
||||
f(`
|
||||
@@ -699,12 +700,13 @@ foo{baz="qwe"} 10
|
||||
bar:1m_increase_prometheus{baz="qwer"} 1
|
||||
foo:1m_increase_prometheus 0
|
||||
foo:1m_increase_prometheus{baz="qwe"} 15
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
|
||||
// multiple aggregate configs
|
||||
f(`
|
||||
- interval: 1m
|
||||
outputs: [count_series, sum_samples]
|
||||
keep_input: true
|
||||
- interval: 5m
|
||||
by: [bar]
|
||||
outputs: [sum_samples]
|
||||
@@ -718,7 +720,7 @@ foo:1m_sum_samples 4.3
|
||||
foo:1m_sum_samples{bar="baz"} 2
|
||||
foo:5m_by_bar_sum_samples 4.3
|
||||
foo:5m_by_bar_sum_samples{bar="baz"} 2
|
||||
`, "111")
|
||||
`, 3)
|
||||
|
||||
// min and max outputs
|
||||
f(`
|
||||
@@ -735,7 +737,7 @@ foo:1m_max{abc="123"} 8.5
|
||||
foo:1m_max{abc="456",de="fg"} 8
|
||||
foo:1m_min{abc="123"} 4
|
||||
foo:1m_min{abc="456",de="fg"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// avg output
|
||||
f(`
|
||||
@@ -749,7 +751,7 @@ foo{abc="456",de="fg"} 8
|
||||
`, `bar:1m_avg 5
|
||||
foo:1m_avg{abc="123"} 6.25
|
||||
foo:1m_avg{abc="456",de="fg"} 8
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// stddev output
|
||||
f(`
|
||||
@@ -763,7 +765,7 @@ foo{abc="456",de="fg"} 8
|
||||
`, `bar:1m_stddev 0
|
||||
foo:1m_stddev{abc="123"} 2.25
|
||||
foo:1m_stddev{abc="456",de="fg"} 0
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// stdvar output
|
||||
f(`
|
||||
@@ -777,7 +779,7 @@ foo{abc="456",de="fg"} 8
|
||||
`, `bar:1m_stdvar 0
|
||||
foo:1m_stdvar{abc="123"} 5.0625
|
||||
foo:1m_stdvar{abc="456",de="fg"} 0
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// histogram_bucket output
|
||||
f(`
|
||||
@@ -795,7 +797,7 @@ cpu_usage{cpu="2"} 90
|
||||
cpu_usage:1m_histogram_bucket{cpu="1",vmrange="1.292e+01...1.468e+01"} 3
|
||||
cpu_usage:1m_histogram_bucket{cpu="1",vmrange="2.448e+01...2.783e+01"} 1
|
||||
cpu_usage:1m_histogram_bucket{cpu="2",vmrange="8.799e+01...1.000e+02"} 1
|
||||
`, "1111111")
|
||||
`, 7)
|
||||
|
||||
// histogram_bucket output without cpu
|
||||
f(`
|
||||
@@ -814,7 +816,7 @@ cpu_usage{cpu="2"} 90
|
||||
cpu_usage:1m_without_cpu_histogram_bucket{vmrange="1.292e+01...1.468e+01"} 3
|
||||
cpu_usage:1m_without_cpu_histogram_bucket{vmrange="2.448e+01...2.783e+01"} 1
|
||||
cpu_usage:1m_without_cpu_histogram_bucket{vmrange="8.799e+01...1.000e+02"} 1
|
||||
`, "1111111")
|
||||
`, 7)
|
||||
|
||||
// quantiles output
|
||||
f(`
|
||||
@@ -834,7 +836,7 @@ cpu_usage:1m_quantiles{cpu="1",quantile="1"} 25
|
||||
cpu_usage:1m_quantiles{cpu="2",quantile="0"} 90
|
||||
cpu_usage:1m_quantiles{cpu="2",quantile="0.5"} 90
|
||||
cpu_usage:1m_quantiles{cpu="2",quantile="1"} 90
|
||||
`, "1111111")
|
||||
`, 7)
|
||||
|
||||
// quantiles output without cpu
|
||||
f(`
|
||||
@@ -852,7 +854,7 @@ cpu_usage{cpu="2"} 90
|
||||
`, `cpu_usage:1m_without_cpu_quantiles{quantile="0"} 12
|
||||
cpu_usage:1m_without_cpu_quantiles{quantile="0.5"} 13.3
|
||||
cpu_usage:1m_without_cpu_quantiles{quantile="1"} 90
|
||||
`, "1111111")
|
||||
`, 7)
|
||||
|
||||
// append additional label
|
||||
f(`
|
||||
@@ -881,7 +883,7 @@ bar-1m-without-abc-sum-samples{new_label="must_keep_metric_name"} 5
|
||||
foo-1m-without-abc-count-samples{new_label="must_keep_metric_name"} 2
|
||||
foo-1m-without-abc-count-series{new_label="must_keep_metric_name"} 1
|
||||
foo-1m-without-abc-sum-samples{new_label="must_keep_metric_name"} 12.5
|
||||
`, "1111")
|
||||
`, 4)
|
||||
|
||||
// test rate_sum and rate_avg
|
||||
f(`
|
||||
@@ -896,7 +898,7 @@ foo{abc="456", cde="1"} 10 10
|
||||
foo 12 34
|
||||
`, `foo:1m_by_cde_rate_avg{cde="1"} 0.325
|
||||
foo:1m_by_cde_rate_sum{cde="1"} 0.65
|
||||
`, "11111")
|
||||
`, 5)
|
||||
|
||||
// rate_sum and rate_avg with duplicated events
|
||||
f(`
|
||||
@@ -905,7 +907,7 @@ foo:1m_by_cde_rate_sum{cde="1"} 0.65
|
||||
`, `
|
||||
foo{abc="123", cde="1"} 4 10
|
||||
foo{abc="123", cde="1"} 4 10
|
||||
`, ``, "11")
|
||||
`, ``, 2)
|
||||
|
||||
// rate_sum and rate_avg for a single sample
|
||||
f(`
|
||||
@@ -914,7 +916,7 @@ foo{abc="123", cde="1"} 4 10
|
||||
`, `
|
||||
foo 4 10
|
||||
bar 5 10
|
||||
`, ``, "11")
|
||||
`, ``, 2)
|
||||
|
||||
// unique_samples output
|
||||
f(`
|
||||
@@ -927,7 +929,7 @@ foo 1 10
|
||||
foo 2 20
|
||||
foo 3 20
|
||||
`, `foo:1m_unique_samples 3
|
||||
`, "11111")
|
||||
`, 5)
|
||||
|
||||
// keep_metric_names
|
||||
f(`
|
||||
@@ -943,7 +945,7 @@ foo{abc="456",de="fg"} 8
|
||||
`, `bar 2
|
||||
foo{abc="123"} 2
|
||||
foo{abc="456",de="fg"} 1
|
||||
`, "11111")
|
||||
`, 5)
|
||||
|
||||
// drop_input_labels
|
||||
f(`
|
||||
@@ -960,11 +962,11 @@ foo{abc="456",de="fg"} 8
|
||||
`, `bar 2
|
||||
foo 2
|
||||
foo{de="fg"} 1
|
||||
`, "11111")
|
||||
`, 5)
|
||||
}
|
||||
|
||||
func TestAggregatorsWithDedupInterval(t *testing.T) {
|
||||
f := func(config, inputMetrics, outputMetricsExpected, matchIdxsStrExpected string) {
|
||||
f := func(config, inputMetrics, outputMetricsExpected string, matchedIdxsExpected int) {
|
||||
t.Helper()
|
||||
|
||||
// Initialize Aggregators
|
||||
@@ -994,16 +996,18 @@ func TestAggregatorsWithDedupInterval(t *testing.T) {
|
||||
// Push the inputMetrics to Aggregators
|
||||
offsetMsecs := time.Now().UnixMilli()
|
||||
tssInput := prompbmarshal.MustParsePromMetrics(inputMetrics, offsetMsecs)
|
||||
matchIdxs := a.Push(tssInput, nil)
|
||||
var matchedIdxs int
|
||||
_ = a.PushWithCallback(tssInput, func(idxs []byte) {
|
||||
for _, idx := range idxs {
|
||||
if idx == 1 {
|
||||
matchedIdxs++
|
||||
}
|
||||
}
|
||||
})
|
||||
a.MustStop()
|
||||
|
||||
// Verify matchIdxs equals to matchIdxsExpected
|
||||
matchIdxsStr := ""
|
||||
for _, v := range matchIdxs {
|
||||
matchIdxsStr += strconv.Itoa(int(v))
|
||||
}
|
||||
if matchIdxsStr != matchIdxsStrExpected {
|
||||
t.Fatalf("unexpected matchIdxs;\ngot\n%s\nwant\n%s", matchIdxsStr, matchIdxsStrExpected)
|
||||
if matchedIdxs != matchedIdxsExpected {
|
||||
t.Fatalf("unexpected matchIdxs;\ngot\n%d\nwant\n%d", matchedIdxs, matchedIdxsExpected)
|
||||
}
|
||||
|
||||
// Verify the tssOutput contains the expected metrics
|
||||
@@ -1026,7 +1030,7 @@ foo 123
|
||||
bar 567
|
||||
`, `bar:1m_sum_samples 567
|
||||
foo:1m_sum_samples 123
|
||||
`, "11")
|
||||
`, 2)
|
||||
|
||||
f(`
|
||||
- interval: 1m
|
||||
@@ -1044,7 +1048,7 @@ foo{baz="qwe"} 10
|
||||
bar:1m_sum_samples{baz="qwer"} 344
|
||||
foo:1m_sum_samples 123
|
||||
foo:1m_sum_samples{baz="qwe"} 10
|
||||
`, "11111111")
|
||||
`, 8)
|
||||
}
|
||||
|
||||
func timeSeriessToString(tss []prompbmarshal.TimeSeries) string {
|
||||
|
||||
@@ -2,12 +2,12 @@ package streamaggr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/stringsutil"
|
||||
)
|
||||
|
||||
var benchOutputs = []string{
|
||||
@@ -43,7 +43,7 @@ func BenchmarkAggregatorsFlushInternalSerial(b *testing.B) {
|
||||
pushFunc := func(_ []prompbmarshal.TimeSeries) {}
|
||||
a := newBenchAggregators(benchOutputs, pushFunc)
|
||||
defer a.MustStop()
|
||||
_ = a.Push(benchSeries, nil)
|
||||
benchSeries = a.Push(benchSeries)
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -66,10 +66,9 @@ func benchmarkAggregatorsPush(b *testing.B, output string) {
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(benchSeries) * loops))
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
var matchIdxs []byte
|
||||
for pb.Next() {
|
||||
for i := 0; i < loops; i++ {
|
||||
matchIdxs = a.Push(benchSeries, matchIdxs)
|
||||
benchSeries = a.Push(benchSeries)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -78,7 +77,7 @@ func benchmarkAggregatorsPush(b *testing.B, output string) {
|
||||
func newBenchAggregators(outputs []string, pushFunc PushFunc) *Aggregators {
|
||||
outputsQuoted := make([]string, len(outputs))
|
||||
for i := range outputs {
|
||||
outputsQuoted[i] = strconv.Quote(outputs[i])
|
||||
outputsQuoted[i] = stringsutil.JSONString(outputs[i])
|
||||
}
|
||||
config := fmt.Sprintf(`
|
||||
- match: http_requests_total
|
||||
|
||||
10
lib/stringsutil/json.go
Normal file
10
lib/stringsutil/json.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package stringsutil
|
||||
|
||||
import (
|
||||
"github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
// JSONString returns JSON-quoted s.
|
||||
func JSONString(s string) string {
|
||||
return string(quicktemplate.AppendJSONString(nil, s, true))
|
||||
}
|
||||
20
lib/stringsutil/json_test.go
Normal file
20
lib/stringsutil/json_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package stringsutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestJSONString(t *testing.T) {
|
||||
f := func(s, resultExpected string) {
|
||||
t.Helper()
|
||||
|
||||
result := JSONString(s)
|
||||
if result != resultExpected {
|
||||
t.Fatalf("unexpected result\ngot\n%s\nwant\n%s", result, resultExpected)
|
||||
}
|
||||
}
|
||||
|
||||
f(``, `""`)
|
||||
f(`foo`, `"foo"`)
|
||||
f("\n\b\f\t\"acЫВА'\\", `"\n\b\f\t\"acЫВА\u0027\\"`)
|
||||
}
|
||||
7
vendor/cloud.google.com/go/auth/CHANGES.md
generated
vendored
7
vendor/cloud.google.com/go/auth/CHANGES.md
generated
vendored
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## [0.7.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.7.0...auth/v0.7.1) (2024-07-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** Bump google.golang.org/grpc@v1.64.1 ([8ecc4e9](https://github.com/googleapis/google-cloud-go/commit/8ecc4e9622e5bbe9b90384d5848ab816027226c5))
|
||||
|
||||
## [0.7.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.6.1...auth/v0.7.0) (2024-07-09)
|
||||
|
||||
|
||||
|
||||
7
vendor/cloud.google.com/go/compute/metadata/CHANGES.md
generated
vendored
7
vendor/cloud.google.com/go/compute/metadata/CHANGES.md
generated
vendored
@@ -1,5 +1,12 @@
|
||||
# Changes
|
||||
|
||||
## [0.5.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.4.0...compute/metadata/v0.5.0) (2024-07-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compute/metadata:** Add sys check for windows OnGCE ([#10521](https://github.com/googleapis/google-cloud-go/issues/10521)) ([3b9a830](https://github.com/googleapis/google-cloud-go/commit/3b9a83063960d2a2ac20beb47cc15818a68bd302))
|
||||
|
||||
## [0.4.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.3.0...compute/metadata/v0.4.0) (2024-07-01)
|
||||
|
||||
|
||||
|
||||
15
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
15
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
@@ -28,7 +28,6 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -190,20 +189,6 @@ func testOnGCE() bool {
|
||||
return <-resc
|
||||
}
|
||||
|
||||
// systemInfoSuggestsGCE reports whether the local system (without
|
||||
// doing network requests) suggests that we're running on GCE. If this
|
||||
// returns true, testOnGCE tries a bit harder to reach its metadata
|
||||
// server.
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
if runtime.GOOS != "linux" {
|
||||
// We don't have any non-Linux clues available, at least yet.
|
||||
return false
|
||||
}
|
||||
slurp, _ := os.ReadFile("/sys/class/dmi/id/product_name")
|
||||
name := strings.TrimSpace(string(slurp))
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
}
|
||||
|
||||
// Subscribe calls Client.SubscribeWithContext on the default client.
|
||||
//
|
||||
// Deprecated: Please use the context aware variant [SubscribeWithContext].
|
||||
|
||||
26
vendor/cloud.google.com/go/compute/metadata/syscheck.go
generated
vendored
Normal file
26
vendor/cloud.google.com/go/compute/metadata/syscheck.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !windows && !linux
|
||||
|
||||
package metadata
|
||||
|
||||
// systemInfoSuggestsGCE reports whether the local system (without
|
||||
// doing network requests) suggests that we're running on GCE. If this
|
||||
// returns true, testOnGCE tries a bit harder to reach its metadata
|
||||
// server.
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
// We don't currently have checks for other GOOS
|
||||
return false
|
||||
}
|
||||
28
vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go
generated
vendored
Normal file
28
vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build linux
|
||||
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
b, _ := os.ReadFile("/sys/class/dmi/id/product_name")
|
||||
name := strings.TrimSpace(string(b))
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
}
|
||||
38
vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go
generated
vendored
Normal file
38
vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\HardwareConfig\Current`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
s, _, err := k.GetStringValue("SystemProductName")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
s = strings.TrimSpace(s)
|
||||
return strings.HasPrefix(s, "Google")
|
||||
}
|
||||
7
vendor/cloud.google.com/go/iam/CHANGES.md
generated
vendored
7
vendor/cloud.google.com/go/iam/CHANGES.md
generated
vendored
@@ -1,6 +1,13 @@
|
||||
# Changes
|
||||
|
||||
|
||||
## [1.1.11](https://github.com/googleapis/google-cloud-go/compare/iam/v1.1.10...iam/v1.1.11) (2024-07-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **iam:** Bump google.golang.org/grpc@v1.64.1 ([8ecc4e9](https://github.com/googleapis/google-cloud-go/commit/8ecc4e9622e5bbe9b90384d5848ab816027226c5))
|
||||
|
||||
## [1.1.10](https://github.com/googleapis/google-cloud-go/compare/iam/v1.1.9...iam/v1.1.10) (2024-07-01)
|
||||
|
||||
|
||||
|
||||
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
generated
vendored
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
generated
vendored
@@ -1,5 +1,11 @@
|
||||
# Release History
|
||||
|
||||
## 1.13.0 (2024-07-16)
|
||||
|
||||
### Features Added
|
||||
|
||||
- Added runtime.NewRequestFromRequest(), allowing for a policy.Request to be created from an existing *http.Request.
|
||||
|
||||
## 1.12.0 (2024-06-06)
|
||||
|
||||
### Features Added
|
||||
|
||||
@@ -192,7 +192,7 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err
|
||||
}
|
||||
|
||||
if strings.EqualFold(parts[0], providersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], providersKey)) {
|
||||
//provider resource can only be on a tenant or a subscription parent
|
||||
// provider resource can only be on a tenant or a subscription parent
|
||||
if parent.ResourceType.String() != SubscriptionResourceType.String() && parent.ResourceType.String() != TenantResourceType.String() {
|
||||
return nil, fmt.Errorf("invalid resource ID: %s", id)
|
||||
}
|
||||
|
||||
8
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go
generated
vendored
8
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go
generated
vendored
@@ -34,18 +34,22 @@ func NewPipeline(module, version string, cred azcore.TokenCredential, plOpts azr
|
||||
InsecureAllowCredentialWithHTTP: options.InsecureAllowCredentialWithHTTP,
|
||||
Scopes: []string{conf.Audience + "/.default"},
|
||||
})
|
||||
// we don't want to modify the underlying array in plOpts.PerRetry
|
||||
perRetry := make([]azpolicy.Policy, len(plOpts.PerRetry), len(plOpts.PerRetry)+1)
|
||||
copy(perRetry, plOpts.PerRetry)
|
||||
plOpts.PerRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy))
|
||||
perRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy))
|
||||
plOpts.PerRetry = perRetry
|
||||
if !options.DisableRPRegistration {
|
||||
regRPOpts := armpolicy.RegistrationOptions{ClientOptions: options.ClientOptions}
|
||||
regPolicy, err := NewRPRegistrationPolicy(cred, ®RPOpts)
|
||||
if err != nil {
|
||||
return azruntime.Pipeline{}, err
|
||||
}
|
||||
// we don't want to modify the underlying array in plOpts.PerCall
|
||||
perCall := make([]azpolicy.Policy, len(plOpts.PerCall), len(plOpts.PerCall)+1)
|
||||
copy(perCall, plOpts.PerCall)
|
||||
plOpts.PerCall = append(perCall, regPolicy)
|
||||
perCall = append(perCall, regPolicy)
|
||||
plOpts.PerCall = perCall
|
||||
}
|
||||
if plOpts.APIVersion.Name == "" {
|
||||
plOpts.APIVersion.Name = "api-version"
|
||||
|
||||
37
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go
generated
vendored
37
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go
generated
vendored
@@ -7,6 +7,7 @@
|
||||
package exported
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
@@ -67,6 +68,42 @@ func (ov opValues) get(value any) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// NewRequestFromRequest creates a new policy.Request with an existing *http.Request
|
||||
// Exported as runtime.NewRequestFromRequest().
|
||||
func NewRequestFromRequest(req *http.Request) (*Request, error) {
|
||||
policyReq := &Request{req: req}
|
||||
|
||||
if req.Body != nil {
|
||||
// we can avoid a body copy here if the underlying stream is already a
|
||||
// ReadSeekCloser.
|
||||
readSeekCloser, isReadSeekCloser := req.Body.(io.ReadSeekCloser)
|
||||
|
||||
if !isReadSeekCloser {
|
||||
// since this is an already populated http.Request we want to copy
|
||||
// over its body, if it has one.
|
||||
bodyBytes, err := io.ReadAll(req.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := req.Body.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
readSeekCloser = NopCloser(bytes.NewReader(bodyBytes))
|
||||
}
|
||||
|
||||
// SetBody also takes care of updating the http.Request's body
|
||||
// as well, so they should stay in-sync from this point.
|
||||
if err := policyReq.SetBody(readSeekCloser, req.Header.Get("Content-Type")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return policyReq, nil
|
||||
}
|
||||
|
||||
// NewRequest creates a new Request with the specified input.
|
||||
// Exported as runtime.NewRequest().
|
||||
func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*Request, error) {
|
||||
|
||||
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
generated
vendored
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
generated
vendored
@@ -40,5 +40,5 @@ const (
|
||||
Module = "azcore"
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
Version = "v1.12.0"
|
||||
Version = "v1.13.0"
|
||||
)
|
||||
|
||||
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
generated
vendored
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
generated
vendored
@@ -15,6 +15,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -45,6 +46,11 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*polic
|
||||
return exported.NewRequest(ctx, httpMethod, endpoint)
|
||||
}
|
||||
|
||||
// NewRequestFromRequest creates a new policy.Request with an existing *http.Request
|
||||
func NewRequestFromRequest(req *http.Request) (*policy.Request, error) {
|
||||
return exported.NewRequestFromRequest(req)
|
||||
}
|
||||
|
||||
// EncodeQueryParams will parse and encode any query parameters in the specified URL.
|
||||
// Any semicolons will automatically be escaped.
|
||||
func EncodeQueryParams(u string) (string, error) {
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package aws
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.30.1"
|
||||
const goModuleVersion = "1.30.3"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.27.26 (2024-07-10.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.27.25 (2024-07-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.27.24 (2024-07-03)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package config
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.27.24"
|
||||
const goModuleVersion = "1.27.26"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.17.26 (2024-07-10.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.17.25 (2024-07-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.17.24 (2024-07-03)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package credentials
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.17.24"
|
||||
const goModuleVersion = "1.17.26"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.16.11 (2024-07-10.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.16.10 (2024-07-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.16.9 (2024-06-28)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package imds
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.16.9"
|
||||
const goModuleVersion = "1.16.11"
|
||||
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.17.7 (2024-07-10.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.17.6 (2024-07-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.17.5 (2024-07-03)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
2
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/feature/s3/manager/go_module_metadata.go
generated
vendored
@@ -3,4 +3,4 @@
|
||||
package manager
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.17.5"
|
||||
const goModuleVersion = "1.17.7"
|
||||
|
||||
225
vendor/github.com/aws/aws-sdk-go-v2/internal/awsutil/path_value.go
generated
vendored
225
vendor/github.com/aws/aws-sdk-go-v2/internal/awsutil/path_value.go
generated
vendored
@@ -1,225 +0,0 @@
|
||||
package awsutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jmespath/go-jmespath"
|
||||
)
|
||||
|
||||
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
|
||||
|
||||
// rValuesAtPath returns a slice of values found in value v. The values
|
||||
// in v are explored recursively so all nested values are collected.
|
||||
func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
|
||||
pathparts := strings.Split(path, "||")
|
||||
if len(pathparts) > 1 {
|
||||
for _, pathpart := range pathparts {
|
||||
vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
|
||||
if len(vals) > 0 {
|
||||
return vals
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))}
|
||||
components := strings.Split(path, ".")
|
||||
for len(values) > 0 && len(components) > 0 {
|
||||
var index *int64
|
||||
var indexStar bool
|
||||
c := strings.TrimSpace(components[0])
|
||||
if c == "" { // no actual component, illegal syntax
|
||||
return nil
|
||||
} else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] {
|
||||
// TODO normalize case for user
|
||||
return nil // don't support unexported fields
|
||||
}
|
||||
|
||||
// parse this component
|
||||
if m := indexRe.FindStringSubmatch(c); m != nil {
|
||||
c = m[1]
|
||||
if m[2] == "" {
|
||||
index = nil
|
||||
indexStar = true
|
||||
} else {
|
||||
i, _ := strconv.ParseInt(m[2], 10, 32)
|
||||
index = &i
|
||||
indexStar = false
|
||||
}
|
||||
}
|
||||
|
||||
nextvals := []reflect.Value{}
|
||||
for _, value := range values {
|
||||
// pull component name out of struct member
|
||||
if value.Kind() != reflect.Struct {
|
||||
continue
|
||||
}
|
||||
|
||||
if c == "*" { // pull all members
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
if f := reflect.Indirect(value.Field(i)); f.IsValid() {
|
||||
nextvals = append(nextvals, f)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
value = value.FieldByNameFunc(func(name string) bool {
|
||||
if c == name {
|
||||
return true
|
||||
} else if !caseSensitive && strings.EqualFold(name, c) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
|
||||
if !value.IsNil() {
|
||||
value.Set(reflect.Zero(value.Type()))
|
||||
}
|
||||
return []reflect.Value{value}
|
||||
}
|
||||
|
||||
if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
|
||||
// TODO if the value is the terminus it should not be created
|
||||
// if the value to be set to its position is nil.
|
||||
value.Set(reflect.New(value.Type().Elem()))
|
||||
value = value.Elem()
|
||||
} else {
|
||||
value = reflect.Indirect(value)
|
||||
}
|
||||
|
||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||
if !createPath && value.IsNil() {
|
||||
value = reflect.ValueOf(nil)
|
||||
}
|
||||
}
|
||||
|
||||
if value.IsValid() {
|
||||
nextvals = append(nextvals, value)
|
||||
}
|
||||
}
|
||||
values = nextvals
|
||||
|
||||
if indexStar || index != nil {
|
||||
nextvals = []reflect.Value{}
|
||||
for _, valItem := range values {
|
||||
value := reflect.Indirect(valItem)
|
||||
if value.Kind() != reflect.Slice {
|
||||
continue
|
||||
}
|
||||
|
||||
if indexStar { // grab all indices
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
idx := reflect.Indirect(value.Index(i))
|
||||
if idx.IsValid() {
|
||||
nextvals = append(nextvals, idx)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// pull out index
|
||||
i := int(*index)
|
||||
if i >= value.Len() { // check out of bounds
|
||||
if createPath {
|
||||
// TODO resize slice
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else if i < 0 { // support negative indexing
|
||||
i = value.Len() + i
|
||||
}
|
||||
value = reflect.Indirect(value.Index(i))
|
||||
|
||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||
if !createPath && value.IsNil() {
|
||||
value = reflect.ValueOf(nil)
|
||||
}
|
||||
}
|
||||
|
||||
if value.IsValid() {
|
||||
nextvals = append(nextvals, value)
|
||||
}
|
||||
}
|
||||
values = nextvals
|
||||
}
|
||||
|
||||
components = components[1:]
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// ValuesAtPath returns a list of values at the case insensitive lexical
|
||||
// path inside of a structure.
|
||||
func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
|
||||
result, err := jmespath.Search(path, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(result)
|
||||
if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) {
|
||||
return nil, nil
|
||||
}
|
||||
if s, ok := result.([]interface{}); ok {
|
||||
return s, err
|
||||
}
|
||||
if v.Kind() == reflect.Map && v.Len() == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if v.Kind() == reflect.Slice {
|
||||
out := make([]interface{}, v.Len())
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
out[i] = v.Index(i).Interface()
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return []interface{}{result}, nil
|
||||
}
|
||||
|
||||
// SetValueAtPath sets a value at the case insensitive lexical path inside
|
||||
// of a structure.
|
||||
func SetValueAtPath(i interface{}, path string, v interface{}) {
|
||||
if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
|
||||
for _, rval := range rvals {
|
||||
if rval.Kind() == reflect.Ptr && rval.IsNil() {
|
||||
continue
|
||||
}
|
||||
setValue(rval, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setValue(dstVal reflect.Value, src interface{}) {
|
||||
if dstVal.Kind() == reflect.Ptr {
|
||||
dstVal = reflect.Indirect(dstVal)
|
||||
}
|
||||
srcVal := reflect.ValueOf(src)
|
||||
|
||||
if !srcVal.IsValid() { // src is literal nil
|
||||
if dstVal.CanAddr() {
|
||||
// Convert to pointer so that pointer's value can be nil'ed
|
||||
// dstVal = dstVal.Addr()
|
||||
}
|
||||
dstVal.Set(reflect.Zero(dstVal.Type()))
|
||||
|
||||
} else if srcVal.Kind() == reflect.Ptr {
|
||||
if srcVal.IsNil() {
|
||||
srcVal = reflect.Zero(dstVal.Type())
|
||||
} else {
|
||||
srcVal = reflect.ValueOf(src).Elem()
|
||||
}
|
||||
dstVal.Set(srcVal)
|
||||
} else {
|
||||
if dstVal.Kind() == reflect.String {
|
||||
dstVal.SetString(srcVal.String())
|
||||
} else {
|
||||
dstVal.Set(srcVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
8
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
generated
vendored
8
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md
generated
vendored
@@ -1,3 +1,11 @@
|
||||
# v1.3.15 (2024-07-10.2)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.3.14 (2024-07-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.3.13 (2024-06-28)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user