Merge branch 'public-single-node' into pmm-6401-read-prometheus-data-files

This commit is contained in:
Aliaksandr Valialkin 2022-11-25 20:13:43 -08:00
commit 8548650c2d
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
175 changed files with 12140 additions and 7879 deletions

View file

@ -289,7 +289,10 @@ When querying the [backfilled data](https://docs.victoriametrics.com/#backfillin
VMUI automatically adjusts the interval between datapoints on the graph depending on the horizontal resolution and on the selected time range. The step value can be customized by changing `Step value` input. VMUI automatically adjusts the interval between datapoints on the graph depending on the horizontal resolution and on the selected time range. The step value can be customized by changing `Step value` input.
VMUI allows investigating correlations between multiple queries on the same graph. Just click `Add Query` button, enter an additional query in the newly appeared input field and press `Ctrl+Enter`. Results for all the queries should be displayed simultaneously on the same graph. VMUI allows investigating correlations between multiple queries on the same graph. Just click `Add Query` button,
enter an additional query in the newly appeared input field and press `Enter`.
Results for all the queries are displayed simultaneously on the same graph.
Graphs for a particular query can be temporarily hidden by clicking the `eye` icon on the right side of the input field.
See the [example VMUI at VictoriaMetrics playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/?g0.expr=100%20*%20sum(rate(process_cpu_seconds_total))%20by%20(job)&g0.range_input=1d). See the [example VMUI at VictoriaMetrics playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/?g0.expr=100%20*%20sum(rate(process_cpu_seconds_total))%20by%20(job)&g0.range_input=1d).
@ -1045,7 +1048,8 @@ Time series data can be imported into VictoriaMetrics via any supported data ing
* `/api/v1/import/native` for importing data obtained from [/api/v1/export/native](#how-to-export-data-in-native-format). * `/api/v1/import/native` for importing data obtained from [/api/v1/export/native](#how-to-export-data-in-native-format).
See [these docs](#how-to-import-data-in-native-format) for details. See [these docs](#how-to-import-data-in-native-format) for details.
* `/api/v1/import/csv` for importing arbitrary CSV data. See [these docs](#how-to-import-csv-data) for details. * `/api/v1/import/csv` for importing arbitrary CSV data. See [these docs](#how-to-import-csv-data) for details.
* `/api/v1/import/prometheus` for importing data in Prometheus exposition format. See [these docs](#how-to-import-data-in-prometheus-exposition-format) for details. * `/api/v1/import/prometheus` for importing data in Prometheus exposition format and in [Pushgateway format](https://github.com/prometheus/pushgateway#url).
See [these docs](#how-to-import-data-in-prometheus-exposition-format) for details.
### How to import data in JSON line format ### How to import data in JSON line format
@ -1150,9 +1154,11 @@ Note that it could be required to flush response cache after importing historica
### How to import data in Prometheus exposition format ### How to import data in Prometheus exposition format
VictoriaMetrics accepts data in [Prometheus exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format) VictoriaMetrics accepts data in [Prometheus exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format),
and in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md) in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md)
via `/api/v1/import/prometheus` path. For example, the following line imports a single line in Prometheus exposition format into VictoriaMetrics: and in [Pushgateway format](https://github.com/prometheus/pushgateway#url) via `/api/v1/import/prometheus` path.
For example, the following command imports a single line in Prometheus exposition format into VictoriaMetrics:
<div class="with-copy" markdown="1"> <div class="with-copy" markdown="1">
@ -1178,6 +1184,16 @@ It should return something like the following:
{"metric":{"__name__":"foo","bar":"baz"},"values":[123],"timestamps":[1594370496905]} {"metric":{"__name__":"foo","bar":"baz"},"values":[123],"timestamps":[1594370496905]}
``` ```
The following command imports a single metric via [Pushgateway format](https://github.com/prometheus/pushgateway#url) with `{job="my_app",instance="host123"}` labels:
<div class="with-copy" markdown="1">
```console
curl -d 'metric{label="abc"} 123' -X POST 'http://localhost:8428/api/v1/import/prometheus/metrics/job/my_app/instance/host123'
```
</div>
Pass `Content-Encoding: gzip` HTTP request header to `/api/v1/import/prometheus` for importing gzipped data: Pass `Content-Encoding: gzip` HTTP request header to `/api/v1/import/prometheus` for importing gzipped data:
<div class="with-copy" markdown="1"> <div class="with-copy" markdown="1">
@ -1189,8 +1205,8 @@ curl -X POST -H 'Content-Encoding: gzip' http://destination-victoriametrics:8428
</div> </div>
Extra labels may be added to all the imported metrics by passing `extra_label=name=value` query args. Extra labels may be added to all the imported metrics either via [Pushgateway format](https://github.com/prometheus/pushgateway#url)
For example, `/api/v1/import/prometheus?extra_label=foo=bar` would add `{foo="bar"}` label to all the imported metrics. or by passing `extra_label=name=value` query args. For example, `/api/v1/import/prometheus?extra_label=foo=bar` would add `{foo="bar"}` label to all the imported metrics.
If timestamp is missing in `<metric> <value> <timestamp>` Prometheus exposition format line, then the current timestamp is used during data ingestion. If timestamp is missing in `<metric> <value> <timestamp>` Prometheus exposition format line, then the current timestamp is used during data ingestion.
It can be overridden by passing unix timestamp in *milliseconds* via `timestamp` query arg. For example, `/api/v1/import/prometheus?timestamp=1594370496905`. It can be overridden by passing unix timestamp in *milliseconds* via `timestamp` query arg. For example, `/api/v1/import/prometheus?timestamp=1594370496905`.
@ -1641,7 +1657,9 @@ All the durations and timestamps in traces are in milliseconds.
Query tracing is allowed by default. It can be denied by passing `-denyQueryTracing` command-line flag to VictoriaMetrics. Query tracing is allowed by default. It can be denied by passing `-denyQueryTracing` command-line flag to VictoriaMetrics.
[VMUI](#vmui) provides an UI for query tracing - just click `Trace query` checkbox and re-run the query in order to investigate its' trace. [VMUI](#vmui) provides an UI:
- for query tracing - just click `Trace query` checkbox and re-run the query in order to investigate its' trace.
- for exploring custom trace - go to the tab `Trace analyzer` and upload or paste JSON with trace information.
## Cardinality limiter ## Cardinality limiter
@ -2030,6 +2048,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
``` ```
-bigMergeConcurrency int -bigMergeConcurrency int
The maximum number of CPU cores to use for big merges. Default value is used if set to 0 The maximum number of CPU cores to use for big merges. Default value is used if set to 0
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-configAuthKey string -configAuthKey string
Authorization key for accessing /config page. It must be passed via authKey query arg Authorization key for accessing /config page. It must be passed via authKey query arg
-csvTrimTimestamp duration -csvTrimTimestamp duration
@ -2048,7 +2068,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-denyQueryTracing -denyQueryTracing
Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing
-downsampling.period array -downsampling.period array
Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in enterprise version of VictoriaMetrics Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-dryRun -dryRun
Whether to check only -promscrape.config and then exit. Unknown config entries aren't allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse=false command-line flag Whether to check only -promscrape.config and then exit. Unknown config entries aren't allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse=false command-line flag
@ -2059,7 +2079,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-finalMergeDelay duration -finalMergeDelay duration
The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge
-flagsAuthKey string -flagsAuthKey string
@ -2163,7 +2183,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-precisionBits int -precisionBits int
The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64) The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64)
-prevCacheRemovalPercent float -prevCacheRemovalPercent float
The previous cache is removed when the percent of requests it serves becomes lower than this value. Higher values reduce average memory usage at the cost of higher CPU usage (default 0.2) Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-promscrape.azureSDCheckInterval duration -promscrape.azureSDCheckInterval duration
Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s) Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s)
-promscrape.cluster.memberNum string -promscrape.cluster.memberNum string
@ -2258,7 +2278,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-relabelDebug -relabelDebug
Whether to log metrics before and after relabeling with -relabelConfig. If the -relabelDebug is enabled, then the metrics aren't sent to storage. This is useful for debugging the relabeling configs Whether to log metrics before and after relabeling with -relabelConfig. If the -relabelDebug is enabled, then the metrics aren't sent to storage. This is useful for debugging the relabeling configs
-retentionFilter array -retentionFilter array
Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in enterprise version of VictoriaMetrics Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-retentionPeriod value -retentionPeriod value
Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter
@ -2272,9 +2292,9 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-search.disableCache -search.disableCache
Whether to disable response caching. This may be useful during data backfilling Whether to disable response caching. This may be useful during data backfilling
-search.graphiteMaxPointsPerSeries int -search.graphiteMaxPointsPerSeries int
The maximum number of points per series Graphite render API can return. This flag is available only in enterprise version of VictoriaMetrics (default 1000000) The maximum number of points per series Graphite render API can return. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 1000000)
-search.graphiteStorageStep duration -search.graphiteStorageStep duration
The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in enterprise version of VictoriaMetrics (default 10s) The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 10s)
-search.latencyOffset duration -search.latencyOffset duration
The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s) The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s)
-search.logSlowQueryDuration duration -search.logSlowQueryDuration duration
@ -2288,7 +2308,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-search.maxFederateSeries int -search.maxFederateSeries int
The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000) The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000)
-search.maxGraphiteSeries int -search.maxGraphiteSeries int
The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in enterprise version of VictoriaMetrics (default 300000) The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 300000)
-search.maxLookback duration -search.maxLookback duration
Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons
-search.maxMemoryPerQuery size -search.maxMemoryPerQuery size

View file

@ -545,7 +545,7 @@ The following articles contain useful information about Prometheus relabeling:
* `keep_metrics`: keeps all the metrics with names matching the given `regex`, * `keep_metrics`: keeps all the metrics with names matching the given `regex`,
while dropping all the other metrics. For example, the following relabeling config keeps metrics while dropping all the other metrics. For example, the following relabeling config keeps metrics
with `fo` and `bar` names, while dropping all the other metrics: with `foo` and `bar` names, while dropping all the other metrics:
```yaml ```yaml
- action: keep_metrics - action: keep_metrics
@ -1107,6 +1107,8 @@ vmagent collects metrics data via popular data ingestion protocols and routes th
See the docs at https://docs.victoriametrics.com/vmagent.html . See the docs at https://docs.victoriametrics.com/vmagent.html .
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-configAuthKey string -configAuthKey string
Authorization key for accessing /config page. It must be passed via authKey query arg Authorization key for accessing /config page. It must be passed via authKey query arg
-csvTrimTimestamp duration -csvTrimTimestamp duration
@ -1127,7 +1129,7 @@ See the docs at https://docs.victoriametrics.com/vmagent.html .
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap
@ -1178,30 +1180,30 @@ See the docs at https://docs.victoriametrics.com/vmagent.html .
-insert.maxQueueDuration duration -insert.maxQueueDuration duration
The maximum duration for waiting in the queue for insert requests due to -maxConcurrentInserts (default 1m0s) The maximum duration for waiting in the queue for insert requests due to -maxConcurrentInserts (default 1m0s)
-kafka.consumer.topic array -kafka.consumer.topic array
Kafka topic names for data consumption. This flag is available only in enterprise version of VictoriaMetrics Kafka topic names for data consumption. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.basicAuth.password array -kafka.consumer.topic.basicAuth.password array
Optional basic auth password for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in enterprise version of VictoriaMetrics Optional basic auth password for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.basicAuth.username array -kafka.consumer.topic.basicAuth.username array
Optional basic auth username for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in enterprise version of VictoriaMetrics Optional basic auth username for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.brokers array -kafka.consumer.topic.brokers array
List of brokers to connect for given topic, e.g. -kafka.consumer.topic.broker=host-1:9092;host-2:9092 . This flag is available only in enterprise version of VictoriaMetrics List of brokers to connect for given topic, e.g. -kafka.consumer.topic.broker=host-1:9092;host-2:9092 . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.defaultFormat string -kafka.consumer.topic.defaultFormat string
Expected data format in the topic if -kafka.consumer.topic.format is skipped. This flag is available only in enterprise version of VictoriaMetrics (default "promremotewrite") Expected data format in the topic if -kafka.consumer.topic.format is skipped. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default "promremotewrite")
-kafka.consumer.topic.format array -kafka.consumer.topic.format array
data format for corresponding kafka topic. Valid formats: influx, prometheus, promremotewrite, graphite, jsonline . This flag is available only in enterprise version of VictoriaMetrics data format for corresponding kafka topic. Valid formats: influx, prometheus, promremotewrite, graphite, jsonline . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.groupID array -kafka.consumer.topic.groupID array
Defines group.id for topic. This flag is available only in enterprise version of VictoriaMetrics Defines group.id for topic. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.isGzipped array -kafka.consumer.topic.isGzipped array
Enables gzip setting for topic messages payload. Only prometheus, jsonline and influx formats accept gzipped messages.This flag is available only in enterprise version of VictoriaMetrics Enables gzip setting for topic messages payload. Only prometheus, jsonline and influx formats accept gzipped messages.This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports array of values separated by comma or specified via multiple flags. Supports array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.options array -kafka.consumer.topic.options array
Optional key=value;key1=value2 settings for topic consumer. See full configuration options at https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md . This flag is available only in enterprise version of VictoriaMetrics Optional key=value;key1=value2 settings for topic consumer. See full configuration options at https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-loggerDisableTimestamps -loggerDisableTimestamps
Whether to disable writing timestamps in logs Whether to disable writing timestamps in logs
@ -1242,6 +1244,8 @@ See the docs at https://docs.victoriametrics.com/vmagent.html .
Trim timestamps for OpenTSDB HTTP data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms) Trim timestamps for OpenTSDB HTTP data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms)
-pprofAuthKey string -pprofAuthKey string
Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings
-prevCacheRemovalPercent float
Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-promscrape.azureSDCheckInterval duration -promscrape.azureSDCheckInterval duration
Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s) Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s)
-promscrape.cluster.memberNum string -promscrape.cluster.memberNum string

View file

@ -217,6 +217,16 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
} }
path := strings.Replace(r.URL.Path, "//", "/", -1) path := strings.Replace(r.URL.Path, "//", "/", -1)
if strings.HasPrefix(path, "/prometheus/api/v1/import/prometheus") || strings.HasPrefix(path, "/api/v1/import/prometheus") {
prometheusimportRequests.Inc()
if err := prometheusimport.InsertHandler(nil, r); err != nil {
prometheusimportErrors.Inc()
httpserver.Errorf(w, r, "%s", err)
return true
}
w.WriteHeader(http.StatusNoContent)
return true
}
if strings.HasPrefix(path, "datadog/") { if strings.HasPrefix(path, "datadog/") {
// Trim suffix from paths starting from /datadog/ in order to support legacy DataDog agent. // Trim suffix from paths starting from /datadog/ in order to support legacy DataDog agent.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2670 // See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2670
@ -250,15 +260,6 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
} }
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
return true return true
case "/prometheus/api/v1/import/prometheus", "/api/v1/import/prometheus":
prometheusimportRequests.Inc()
if err := prometheusimport.InsertHandler(nil, r); err != nil {
prometheusimportErrors.Inc()
httpserver.Errorf(w, r, "%s", err)
return true
}
w.WriteHeader(http.StatusNoContent)
return true
case "/prometheus/api/v1/import/native", "/api/v1/import/native": case "/prometheus/api/v1/import/native", "/api/v1/import/native":
nativeimportRequests.Inc() nativeimportRequests.Inc()
if err := native.InsertHandler(nil, r); err != nil { if err := native.InsertHandler(nil, r); err != nil {
@ -409,6 +410,16 @@ func processMultitenantRequest(w http.ResponseWriter, r *http.Request, path stri
httpserver.Errorf(w, r, "cannot obtain auth token: %s", err) httpserver.Errorf(w, r, "cannot obtain auth token: %s", err)
return true return true
} }
if strings.HasPrefix(p.Suffix, "prometheus/api/v1/import/prometheus") {
prometheusimportRequests.Inc()
if err := prometheusimport.InsertHandler(at, r); err != nil {
prometheusimportErrors.Inc()
httpserver.Errorf(w, r, "%s", err)
return true
}
w.WriteHeader(http.StatusNoContent)
return true
}
if strings.HasPrefix(p.Suffix, "datadog/") { if strings.HasPrefix(p.Suffix, "datadog/") {
// Trim suffix from paths starting from /datadog/ in order to support legacy DataDog agent. // Trim suffix from paths starting from /datadog/ in order to support legacy DataDog agent.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2670 // See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2670
@ -442,15 +453,6 @@ func processMultitenantRequest(w http.ResponseWriter, r *http.Request, path stri
} }
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
return true return true
case "prometheus/api/v1/import/prometheus":
prometheusimportRequests.Inc()
if err := prometheusimport.InsertHandler(at, r); err != nil {
prometheusimportErrors.Inc()
httpserver.Errorf(w, r, "%s", err)
return true
}
w.WriteHeader(http.StatusNoContent)
return true
case "prometheus/api/v1/import/native": case "prometheus/api/v1/import/native":
nativeimportRequests.Inc() nativeimportRequests.Inc()
if err := native.InsertHandler(at, r); err != nil { if err := native.InsertHandler(at, r); err != nil {

View file

@ -13,6 +13,7 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bloomfilter" "github.com/VictoriaMetrics/VictoriaMetrics/lib/bloomfilter"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil" "github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup" "github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil" "github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger" "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/memory" "github.com/VictoriaMetrics/VictoriaMetrics/lib/memory"
@ -139,6 +140,8 @@ func Init() {
logger.Fatalf("cannot load relabel configs: %s", err) logger.Fatalf("cannot load relabel configs: %s", err)
} }
allRelabelConfigs.Store(rcs) allRelabelConfigs.Store(rcs)
configSuccess.Set(1)
configTimestamp.Set(fasttime.UnixTimestamp())
if len(*remoteWriteURLs) > 0 { if len(*remoteWriteURLs) > 0 {
rwctxsDefault = newRemoteWriteCtxs(nil, *remoteWriteURLs) rwctxsDefault = newRemoteWriteCtxs(nil, *remoteWriteURLs)
@ -154,18 +157,31 @@ func Init() {
case <-stopCh: case <-stopCh:
return return
} }
configReloads.Inc()
logger.Infof("SIGHUP received; reloading relabel configs pointed by -remoteWrite.relabelConfig and -remoteWrite.urlRelabelConfig") logger.Infof("SIGHUP received; reloading relabel configs pointed by -remoteWrite.relabelConfig and -remoteWrite.urlRelabelConfig")
rcs, err := loadRelabelConfigs() rcs, err := loadRelabelConfigs()
if err != nil { if err != nil {
configReloadErrors.Inc()
configSuccess.Set(0)
logger.Errorf("cannot reload relabel configs; preserving the previous configs; error: %s", err) logger.Errorf("cannot reload relabel configs; preserving the previous configs; error: %s", err)
continue continue
} }
allRelabelConfigs.Store(rcs) allRelabelConfigs.Store(rcs)
configSuccess.Set(1)
configTimestamp.Set(fasttime.UnixTimestamp())
logger.Infof("Successfully reloaded relabel configs") logger.Infof("Successfully reloaded relabel configs")
} }
}() }()
} }
var (
configReloads = metrics.NewCounter(`vmagent_relabel_config_reloads_total`)
configReloadErrors = metrics.NewCounter(`vmagent_relabel_config_reloads_errors_total`)
configSuccess = metrics.NewCounter(`vmagent_relabel_config_last_reload_successful`)
configTimestamp = metrics.NewCounter(`vmagent_relabel_config_last_reload_success_timestamp_seconds`)
)
func newRemoteWriteCtxs(at *auth.Token, urls []string) []*remoteWriteCtx { func newRemoteWriteCtxs(at *auth.Token, urls []string) []*remoteWriteCtx {
if len(urls) == 0 { if len(urls) == 0 {
logger.Panicf("BUG: urls must be non-empty") logger.Panicf("BUG: urls must be non-empty")

View file

@ -673,10 +673,12 @@ See full description for these flags in `./vmalert -help`.
## Monitoring ## Monitoring
`vmalert` exports various metrics in Prometheus exposition format at `http://vmalert-host:8880/metrics` page. `vmalert` exports various metrics in Prometheus exposition format at `http://vmalert-host:8880/metrics` page.
The default list of alerting rules for these metric can be found [here](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker).
We recommend setting up regular scraping of this page either through `vmagent` or by Prometheus so that the exported We recommend setting up regular scraping of this page either through `vmagent` or by Prometheus so that the exported
metrics may be analyzed later. metrics may be analyzed later.
Use the official [Grafana dashboard](https://grafana.com/grafana/dashboards/14950) for `vmalert` overview. Graphs on this dashboard contain useful hints - hover the `i` icon at the top left corner of each graph in order to read it. Use the official [Grafana dashboard](https://grafana.com/grafana/dashboards/14950) for `vmalert` overview.
Graphs on this dashboard contain useful hints - hover the `i` icon in the top left corner of each graph in order to read it.
If you have suggestions for improvements or have found a bug - please open an issue on github or add If you have suggestions for improvements or have found a bug - please open an issue on github or add
a review to the dashboard. a review to the dashboard.
@ -781,7 +783,7 @@ The shortlist of configuration flags is the following:
{% raw %} {% raw %}
``` ```
-clusterMode -clusterMode
If clusterMode is enabled, then vmalert automatically adds the tenant specified in config groups to -datasource.url, -remoteWrite.url and -remoteRead.url. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in enterprise version of VictoriaMetrics If clusterMode is enabled, then vmalert automatically adds the tenant specified in config groups to -datasource.url, -remoteWrite.url and -remoteRead.url. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-configCheckInterval duration -configCheckInterval duration
Interval for checking for changes in '-rule' or '-notifier.config' files. By default the checking is disabled. Send SIGHUP signal in order to force config check for changes. Interval for checking for changes in '-rule' or '-notifier.config' files. By default the checking is disabled. Send SIGHUP signal in order to force config check for changes.
-datasource.appendTypePrefix -datasource.appendTypePrefix
@ -835,9 +837,9 @@ The shortlist of configuration flags is the following:
-datasource.url string -datasource.url string
Datasource compatible with Prometheus HTTP API. It can be single node VictoriaMetrics or vmselect URL. Required parameter. E.g. http://127.0.0.1:8428 . See also '-datasource.disablePathAppend', '-datasource.showURL'. Datasource compatible with Prometheus HTTP API. It can be single node VictoriaMetrics or vmselect URL. Required parameter. E.g. http://127.0.0.1:8428 . See also '-datasource.disablePathAppend', '-datasource.showURL'.
-defaultTenant.graphite string -defaultTenant.graphite string
Default tenant for Graphite alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy .This flag is available only in enterprise version of VictoriaMetrics Default tenant for Graphite alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy .This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-defaultTenant.prometheus string -defaultTenant.prometheus string
Default tenant for Prometheus alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in enterprise version of VictoriaMetrics Default tenant for Prometheus alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-disableAlertgroupLabel -disableAlertgroupLabel
Whether to disable adding group's Name as label to generated alerts and time series. Whether to disable adding group's Name as label to generated alerts and time series.
-dryRun -dryRun
@ -849,12 +851,11 @@ The shortlist of configuration flags is the following:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-evaluationInterval duration -evaluationInterval duration
How often to evaluate the rules (default 1m0s) How often to evaluate the rules (default 1m0s)
-external.alert.source string -external.alert.source string
External Alert Source allows to override the Source link for alerts sent to AlertManager for cases where you want to build a custom link to Grafana, Prometheus or any other service. Supports templating - see https://docs.victoriametrics.com/vmalert.html#templating . For example, link to Grafana: -external.alert.source='explore?orgId=1&left=["now-1h","now","VictoriaMetrics",{"expr":{{$expr|jsonEscape|queryEscape}} },{"mode":"Metrics"},{"ui":[true,true,true,"none"]}]' . If empty 'vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}' is used External Alert Source allows to override the Source link for alerts sent to AlertManager for cases where you want to build a custom link to Grafana, Prometheus or any other service. Supports templating - see https://docs.victoriametrics.com/vmalert.html#templating . For example, link to Grafana: -external.alert.source='explore?orgId=1&left=["now-1h","now","VictoriaMetrics",{"expr":{{$expr|jsonEscape|queryEscape}} },{"mode":"Metrics"},{"ui":[true,true,true,"none"]}]' . If empty 'vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}' is used.
If empty 'vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}' is used.
-external.label array -external.label array
Optional label in the form 'Name=value' to add to all generated recording rules and alerts. Pass multiple -label flags in order to add multiple label sets. Optional label in the form 'Name=value' to add to all generated recording rules and alerts. Pass multiple -label flags in order to add multiple label sets.
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.

View file

@ -239,7 +239,7 @@ See the docs at https://docs.victoriametrics.com/vmauth.html .
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -196,7 +196,7 @@ See [this article](https://medium.com/@valyala/speeding-up-backups-for-big-time-
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -299,6 +299,13 @@ The shortlist of configuration flags is the following:
``` ```
vmbackupmanager performs regular backups according to the provided configs. vmbackupmanager performs regular backups according to the provided configs.
subcommands:
backup: provides auxiliary backup-related commands
restore: restores backup specified by restore mark if it exists
command-line flags:
-apiURL string
vmbackupmanager address to perform API requests (default "http://127.0.0.1:8300")
-concurrency int -concurrency int
The number of concurrent workers. Higher concurrency may reduce backup duration (default 10) The number of concurrent workers. Higher concurrency may reduce backup duration (default 10)
-configFilePath string -configFilePath string
@ -328,7 +335,7 @@ vmbackupmanager performs regular backups according to the provided configs.
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap
@ -392,8 +399,6 @@ vmbackupmanager performs regular backups according to the provided configs.
-pushmetrics.url array -pushmetrics.url array
Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-restoreOnStart
Check if backup restore was requested and restore requested backup.
-runOnStart -runOnStart
Upload backups immediately after start of the service. Otherwise the backup starts on new hour Upload backups immediately after start of the service. Otherwise the backup starts on new hour
-s3ForcePathStyle -s3ForcePathStyle

View file

@ -176,8 +176,8 @@ curl 'http://localhost:8431/api/v1/labels' -H 'Authorization: Bearer eyJhbGciOiJ
The shortlist of configuration flags include the following: The shortlist of configuration flags include the following:
```console ```console
-auth.httpHeader -auth.httpHeader string
HTTP header name to look for JWT authorization token HTTP header name to look for JWT authorization token (default "Authorization")
-clusterMode -clusterMode
enable this for the cluster version enable this for the cluster version
-datasource.appendTypePrefix -datasource.appendTypePrefix
@ -211,7 +211,7 @@ The shortlist of configuration flags include the following:
-datasource.oauth2.tokenUrl string -datasource.oauth2.tokenUrl string
Optional OAuth2 tokenURL to use for -datasource.url. Optional OAuth2 tokenURL to use for -datasource.url.
-datasource.queryStep duration -datasource.queryStep duration
queryStep defines how far a value can fallback to when evaluating queries. For example, if datasource.queryStep=15s then param "step" with value "15s" will be added to every query.If queryStep isn't specified, rule's evaluationInterval will be used instead. How far a value can fallback to when evaluating queries. For example, if -datasource.queryStep=15s then param "step" with value "15s" will be added to every query. If set to 0, rule's evaluation interval will be used instead. (default 5m0s)
-datasource.queryTimeAlignment -datasource.queryTimeAlignment
Whether to align "time" parameter with evaluation interval.Alignment supposed to produce deterministic results despite of number of vmalert replicas or time they were started. See more details here https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1257 (default true) Whether to align "time" parameter with evaluation interval.Alignment supposed to produce deterministic results despite of number of vmalert replicas or time they were started. See more details here https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1257 (default true)
-datasource.roundDigits int -datasource.roundDigits int
@ -241,7 +241,7 @@ The shortlist of configuration flags include the following:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -120,6 +120,16 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
staticServer.ServeHTTP(w, r) staticServer.ServeHTTP(w, r)
return true return true
} }
if strings.HasPrefix(path, "/prometheus/api/v1/import/prometheus") || strings.HasPrefix(path, "/api/v1/import/prometheus") {
prometheusimportRequests.Inc()
if err := prometheusimport.InsertHandler(r); err != nil {
prometheusimportErrors.Inc()
httpserver.Errorf(w, r, "%s", err)
return true
}
w.WriteHeader(http.StatusNoContent)
return true
}
if strings.HasPrefix(path, "/datadog/") { if strings.HasPrefix(path, "/datadog/") {
// Trim suffix from paths starting from /datadog/ in order to support legacy DataDog agent. // Trim suffix from paths starting from /datadog/ in order to support legacy DataDog agent.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2670 // See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2670
@ -153,15 +163,6 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
} }
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
return true return true
case "/prometheus/api/v1/import/prometheus", "/api/v1/import/prometheus":
prometheusimportRequests.Inc()
if err := prometheusimport.InsertHandler(r); err != nil {
prometheusimportErrors.Inc()
httpserver.Errorf(w, r, "%s", err)
return true
}
w.WriteHeader(http.StatusNoContent)
return true
case "/prometheus/api/v1/import/native", "/api/v1/import/native": case "/prometheus/api/v1/import/native", "/api/v1/import/native":
nativeimportRequests.Inc() nativeimportRequests.Inc()
if err := native.InsertHandler(r); err != nil { if err := native.InsertHandler(r); err != nil {

View file

@ -6,6 +6,7 @@ import (
"sync/atomic" "sync/atomic"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil" "github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger" "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/procutil" "github.com/VictoriaMetrics/VictoriaMetrics/lib/procutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompb" "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompb"
@ -38,23 +39,38 @@ func Init() {
logger.Fatalf("cannot load relabelConfig: %s", err) logger.Fatalf("cannot load relabelConfig: %s", err)
} }
pcsGlobal.Store(pcs) pcsGlobal.Store(pcs)
configSuccess.Set(1)
configTimestamp.Set(fasttime.UnixTimestamp())
if len(*relabelConfig) == 0 { if len(*relabelConfig) == 0 {
return return
} }
go func() { go func() {
for range sighupCh { for range sighupCh {
configReloads.Inc()
logger.Infof("received SIGHUP; reloading -relabelConfig=%q...", *relabelConfig) logger.Infof("received SIGHUP; reloading -relabelConfig=%q...", *relabelConfig)
pcs, err := loadRelabelConfig() pcs, err := loadRelabelConfig()
if err != nil { if err != nil {
configReloadErrors.Inc()
configSuccess.Set(0)
logger.Errorf("cannot load the updated relabelConfig: %s; preserving the previous config", err) logger.Errorf("cannot load the updated relabelConfig: %s; preserving the previous config", err)
continue continue
} }
pcsGlobal.Store(pcs) pcsGlobal.Store(pcs)
configSuccess.Set(1)
configTimestamp.Set(fasttime.UnixTimestamp())
logger.Infof("successfully reloaded -relabelConfig=%q", *relabelConfig) logger.Infof("successfully reloaded -relabelConfig=%q", *relabelConfig)
} }
}() }()
} }
var (
configReloads = metrics.NewCounter(`vm_relabel_config_reloads_total`)
configReloadErrors = metrics.NewCounter(`vm_relabel_config_reloads_errors_total`)
configSuccess = metrics.NewCounter(`vm_relabel_config_last_reload_successful`)
configTimestamp = metrics.NewCounter(`vm_relabel_config_last_reload_success_timestamp_seconds`)
)
var pcsGlobal atomic.Value var pcsGlobal atomic.Value
func loadRelabelConfig() (*promrelabel.ParsedConfigs, error) { func loadRelabelConfig() (*promrelabel.ParsedConfigs, error) {

View file

@ -100,7 +100,7 @@ i.e. the end result would be similar to [rsync --delete](https://askubuntu.com/q
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -1090,7 +1090,10 @@ func ProcessSearchQuery(qt *querytracer.Tracer, sq *storage.SearchQuery, deadlin
startTime := time.Now() startTime := time.Now()
maxSeriesCount := sr.Init(qt, vmstorage.Storage, tfss, tr, sq.MaxMetrics, deadline.Deadline()) maxSeriesCount := sr.Init(qt, vmstorage.Storage, tfss, tr, sq.MaxMetrics, deadline.Deadline())
indexSearchDuration.UpdateDuration(startTime) indexSearchDuration.UpdateDuration(startTime)
m := make(map[string][]blockRef, maxSeriesCount) type blockRefs struct {
brs []blockRef
}
m := make(map[string]*blockRefs, maxSeriesCount)
orderedMetricNames := make([]string, 0, maxSeriesCount) orderedMetricNames := make([]string, 0, maxSeriesCount)
blocksRead := 0 blocksRead := 0
samples := 0 samples := 0
@ -1119,13 +1122,14 @@ func ProcessSearchQuery(qt *querytracer.Tracer, sq *storage.SearchQuery, deadlin
} }
metricName := sr.MetricBlockRef.MetricName metricName := sr.MetricBlockRef.MetricName
brs := m[string(metricName)] brs := m[string(metricName)]
brs = append(brs, blockRef{ if brs == nil {
brs = &blockRefs{}
}
brs.brs = append(brs.brs, blockRef{
partRef: br.PartRef(), partRef: br.PartRef(),
addr: addr, addr: addr,
}) })
if len(brs) > 1 { if len(brs.brs) == 1 {
m[string(metricName)] = brs
} else {
// An optimization for big number of time series with long metricName values: // An optimization for big number of time series with long metricName values:
// use only a single copy of metricName for both orderedMetricNames and m. // use only a single copy of metricName for both orderedMetricNames and m.
orderedMetricNames = append(orderedMetricNames, string(metricName)) orderedMetricNames = append(orderedMetricNames, string(metricName))
@ -1174,7 +1178,7 @@ func ProcessSearchQuery(qt *querytracer.Tracer, sq *storage.SearchQuery, deadlin
for i, metricName := range orderedMetricNames { for i, metricName := range orderedMetricNames {
pts[i] = packedTimeseries{ pts[i] = packedTimeseries{
metricName: metricName, metricName: metricName,
brs: m[metricName], brs: m[metricName].brs,
pd: pm[metricName], pd: pm[metricName],
} }
} }

View file

@ -488,6 +488,12 @@ func execBinaryOpArgs(qt *querytracer.Tracer, ec *EvalConfig, exprFirst, exprSec
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if len(tssFirst) == 0 && strings.ToLower(be.Op) != "or" {
// Fast path: there is no sense in executing the exprSecond when exprFirst returns an empty result,
// since the "exprFirst op exprSecond" would return an empty result in any case.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3349
return nil, nil, nil
}
lfs := getCommonLabelFilters(tssFirst) lfs := getCommonLabelFilters(tssFirst)
lfs = metricsql.TrimFiltersByGroupModifier(lfs, be) lfs = metricsql.TrimFiltersByGroupModifier(lfs, be)
exprSecond = metricsql.PushdownBinaryOpFilters(exprSecond, lfs) exprSecond = metricsql.PushdownBinaryOpFilters(exprSecond, lfs)

View file

@ -2281,6 +2281,16 @@ func TestExecSuccess(t *testing.T) {
resultExpected := []netstorage.Result{r} resultExpected := []netstorage.Result{r}
f(q, resultExpected) f(q, resultExpected)
}) })
t.Run(`limit_offset(too-big-offset)`, func(t *testing.T) {
t.Parallel()
q := `limit_offset(1, 10, sort_by_label((
label_set(time()*1, "foo", "y"),
label_set(time()*2, "foo", "a"),
label_set(time()*3, "foo", "x"),
), "foo"))`
resultExpected := []netstorage.Result{}
f(q, resultExpected)
})
t.Run(`limit_offset NaN`, func(t *testing.T) { t.Run(`limit_offset NaN`, func(t *testing.T) {
t.Parallel() t.Parallel()
// q returns 3 time series, where foo=3 contains only NaN values // q returns 3 time series, where foo=3 contains only NaN values
@ -6892,6 +6902,23 @@ func TestExecSuccess(t *testing.T) {
resultExpected := []netstorage.Result{r} resultExpected := []netstorage.Result{r}
f(q, resultExpected) f(q, resultExpected)
}) })
t.Run(`range_normalize(time(),alias(-time(),"negative"))`, func(t *testing.T) {
t.Parallel()
q := `range_normalize(time(),alias(-time(), "negative"))`
r1 := netstorage.Result{
MetricName: metricNameExpected,
Values: []float64{0, 0.2, 0.4, 0.6, 0.8, 1},
Timestamps: timestampsExpected,
}
r2 := netstorage.Result{
MetricName: metricNameExpected,
Values: []float64{1, 0.8, 0.6, 0.4, 0.2, 0},
Timestamps: timestampsExpected,
}
r2.MetricName.MetricGroup = []byte("negative")
resultExpected := []netstorage.Result{r1, r2}
f(q, resultExpected)
})
t.Run(`range_first(time())`, func(t *testing.T) { t.Run(`range_first(time())`, func(t *testing.T) {
t.Parallel() t.Parallel()
q := `range_first(time())` q := `range_first(time())`

View file

@ -91,6 +91,7 @@ var transformFuncs = map[string]transformFunc{
"range_linear_regression": transformRangeLinearRegression, "range_linear_regression": transformRangeLinearRegression,
"range_max": newTransformFuncRange(runningMax), "range_max": newTransformFuncRange(runningMax),
"range_min": newTransformFuncRange(runningMin), "range_min": newTransformFuncRange(runningMin),
"range_normalize": transformRangeNormalize,
"range_quantile": transformRangeQuantile, "range_quantile": transformRangeQuantile,
"range_stddev": transformRangeStddev, "range_stddev": transformRangeStddev,
"range_stdvar": transformRangeStdvar, "range_stdvar": transformRangeStdvar,
@ -142,6 +143,7 @@ var transformFuncsKeepMetricName = map[string]bool{
"range_linear_regression": true, "range_linear_regression": true,
"range_max": true, "range_max": true,
"range_min": true, "range_min": true,
"range_normalize": true,
"range_quantile": true, "range_quantile": true,
"range_stdvar": true, "range_stdvar": true,
"range_sddev": true, "range_sddev": true,
@ -1240,6 +1242,38 @@ func newTransformFuncRange(rf func(a, b float64, idx int) float64) transformFunc
} }
} }
func transformRangeNormalize(tfa *transformFuncArg) ([]*timeseries, error) {
args := tfa.args
var rvs []*timeseries
for _, tss := range args {
for _, ts := range tss {
values := ts.Values
vMin := inf
vMax := -inf
for _, v := range values {
if math.IsNaN(v) {
continue
}
if v < vMin {
vMin = v
}
if v > vMax {
vMax = v
}
}
d := vMax - vMin
if math.IsInf(d, 0) {
continue
}
for i, v := range values {
values[i] = (v - vMin) / d
}
rvs = append(rvs, ts)
}
}
return rvs, nil
}
func transformRangeLinearRegression(tfa *transformFuncArg) ([]*timeseries, error) { func transformRangeLinearRegression(tfa *transformFuncArg) ([]*timeseries, error) {
args := tfa.args args := tfa.args
if err := expectTransformArgsNum(args, 1); err != nil { if err := expectTransformArgsNum(args, 1); err != nil {
@ -1943,6 +1977,8 @@ func transformLimitOffset(tfa *transformFuncArg) ([]*timeseries, error) {
rvs := removeEmptySeries(args[2]) rvs := removeEmptySeries(args[2])
if len(rvs) >= offset { if len(rvs) >= offset {
rvs = rvs[offset:] rvs = rvs[offset:]
} else {
rvs = nil
} }
if len(rvs) > limit { if len(rvs) > limit {
rvs = rvs[:limit] rvs = rvs[:limit]

View file

@ -1,12 +1,12 @@
{ {
"files": { "files": {
"main.css": "./static/css/main.0493d695.css", "main.css": "./static/css/main.0937c83d.css",
"main.js": "./static/js/main.0b7317e2.js", "main.js": "./static/js/main.e18cda26.js",
"static/js/27.c1ccfd29.chunk.js": "./static/js/27.c1ccfd29.chunk.js", "static/js/27.c1ccfd29.chunk.js": "./static/js/27.c1ccfd29.chunk.js",
"index.html": "./index.html" "index.html": "./index.html"
}, },
"entrypoints": [ "entrypoints": [
"static/css/main.0493d695.css", "static/css/main.0937c83d.css",
"static/js/main.0b7317e2.js" "static/js/main.e18cda26.js"
] ]
} }

View file

@ -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"/><meta name="theme-color" content="#000000"/><meta name="description" content="VM-UI is a metric explorer for Victoria Metrics"/><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><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&family=Lato:wght@300;400;700&display=swap" rel="stylesheet"><script src="./dashboards/index.js" type="module"></script><script defer="defer" src="./static/js/main.0b7317e2.js"></script><link href="./static/css/main.0493d695.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"/><meta name="theme-color" content="#000000"/><meta name="description" content="VM-UI is a metric explorer for Victoria Metrics"/><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><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&family=Lato:wght@300;400;700&display=swap" rel="stylesheet"><script src="./dashboards/index.js" type="module"></script><script defer="defer" src="./static/js/main.e18cda26.js"></script><link href="./static/css/main.0937c83d.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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@ COPY web/ /build/
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o web-amd64 github.com/VictoriMetrics/vmui/ && \ RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o web-amd64 github.com/VictoriMetrics/vmui/ && \
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o web-windows github.com/VictoriMetrics/vmui/ GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o web-windows github.com/VictoriMetrics/vmui/
FROM alpine:3.16.2 FROM alpine:3.17.0
USER root USER root
COPY --from=build-web-stage /build/web-amd64 /app/web COPY --from=build-web-stage /build/web-amd64 /app/web

View file

@ -9,6 +9,7 @@ import CardinalityPanel from "./pages/CardinalityPanel";
import TopQueries from "./pages/TopQueries"; import TopQueries from "./pages/TopQueries";
import ThemeProvider from "./components/Main/ThemeProvider/ThemeProvider"; import ThemeProvider from "./components/Main/ThemeProvider/ThemeProvider";
import Spinner from "./components/Main/Spinner/Spinner"; import Spinner from "./components/Main/Spinner/Spinner";
import TracePage from "./pages/TracePage";
const App: FC = () => { const App: FC = () => {
@ -45,6 +46,10 @@ const App: FC = () => {
path={router.topQueries} path={router.topQueries}
element={<TopQueries/>} element={<TopQueries/>}
/> />
<Route
path={router.trace}
element={<TracePage/>}
/>
</Route> </Route>
</Routes> </Routes>
</AppContextProvider> </AppContextProvider>

View file

@ -0,0 +1,181 @@
import React, { FC, useEffect, useMemo, useRef, useState } from "preact/compat";
import uPlot, { Series } from "uplot";
import { MetricResult } from "../../../api/types";
import { formatPrettyNumber, getColorLine, getLegendLabel } from "../../../utils/uplot/helpers";
import dayjs from "dayjs";
import { DATE_FULL_TIMEZONE_FORMAT } from "../../../constants/date";
import ReactDOM from "react-dom";
import get from "lodash.get";
import Button from "../../Main/Button/Button";
import { CloseIcon, DragIcon } from "../../Main/Icons";
import classNames from "classnames";
import { MouseEvent as ReactMouseEvent } from "react";
import "./style.scss";
export interface ChartTooltipProps {
id: string,
u: uPlot,
metrics: MetricResult[],
series: Series[],
unit?: string,
isSticky?: boolean,
tooltipOffset: { left: number, top: number },
tooltipIdx: { seriesIdx: number, dataIdx: number },
onClose?: (id: string) => void
}
const ChartTooltip: FC<ChartTooltipProps> = ({
u,
id,
unit = "",
metrics,
series,
tooltipIdx,
tooltipOffset,
isSticky,
onClose
}) => {
const tooltipRef = useRef<HTMLDivElement>(null);
const [position, setPosition] = useState({ top: -999, left: -999 });
const [moving, setMoving] = useState(false);
const [moved, setMoved] = useState(false);
const [seriesIdx, setSeriesIdx] = useState(tooltipIdx.seriesIdx);
const [dataIdx, setDataIdx] = useState(tooltipIdx.dataIdx);
const targetPortal = useMemo(() => u.root.querySelector(".u-wrap"), [u]);
const value = useMemo(() => get(u, ["data", seriesIdx, dataIdx], 0), [u, seriesIdx, dataIdx]);
const valueFormat = useMemo(() => formatPrettyNumber(value), [value]);
const dataTime = useMemo(() => u.data[0][dataIdx], [u, dataIdx]);
const date = useMemo(() => dayjs(new Date(dataTime * 1000)).format(DATE_FULL_TIMEZONE_FORMAT), [dataTime]);
const color = useMemo(() => getColorLine(series[seriesIdx]?.label || ""), [series, seriesIdx]);
const name = useMemo(() => {
const metricName = (series[seriesIdx]?.label || "").replace(/{.+}/gmi, "").trim();
return getLegendLabel(metricName);
}, []);
const fields = useMemo(() => {
const metric = metrics[seriesIdx - 1]?.metric || {};
const fields = Object.keys(metric).filter(k => k !== "__name__");
return fields.map(key => `${key}="${metric[key]}"`);
}, [metrics, seriesIdx]);
const handleClose = () => {
onClose && onClose(id);
};
const handleMouseDown = (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
setMoved(true);
setMoving(true);
const { clientX, clientY } = e;
setPosition({ top: clientY, left: clientX });
};
const handleMouseMove = (e: MouseEvent) => {
if (!moving) return;
const { clientX, clientY } = e;
setPosition({ top: clientY, left: clientX });
};
const handleMouseUp = () => {
setMoving(false);
};
const calcPosition = () => {
if (!tooltipRef.current) return;
const topOnChart = u.valToPos((value || 0), series[seriesIdx]?.scale || "1");
const leftOnChart = u.valToPos(dataTime, "x");
const { width: tooltipWidth, height: tooltipHeight } = tooltipRef.current.getBoundingClientRect();
const { width, height } = u.over.getBoundingClientRect();
const margin = 10;
const overflowX = leftOnChart + tooltipWidth >= width ? tooltipWidth + (2 * margin) : 0;
const overflowY = topOnChart + tooltipHeight >= height ? tooltipHeight + (2 * margin) : 0;
setPosition({
top: topOnChart + tooltipOffset.top + margin - overflowY,
left: leftOnChart + tooltipOffset.left + margin - overflowX
});
};
useEffect(calcPosition, [u, value, dataTime, seriesIdx, tooltipOffset, tooltipRef]);
useEffect(() => {
setSeriesIdx(tooltipIdx.seriesIdx);
setDataIdx(tooltipIdx.dataIdx);
}, [tooltipIdx]);
useEffect(() => {
if (moving) {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
}
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
}, [moving]);
if (!targetPortal || tooltipIdx.seriesIdx < 0 || tooltipIdx.dataIdx < 0) return null;
return ReactDOM.createPortal((
<div
className={classNames({
"vm-chart-tooltip": true,
"vm-chart-tooltip_sticky": isSticky,
"vm-chart-tooltip_moved": moved
})}
ref={tooltipRef}
style={position}
>
<div className="vm-chart-tooltip-header">
<div className="vm-chart-tooltip-header__date">{date}</div>
{isSticky && (
<>
<Button
className="vm-chart-tooltip-header__drag"
variant="text"
size="small"
startIcon={<DragIcon/>}
onMouseDown={handleMouseDown}
/>
<Button
className="vm-chart-tooltip-header__close"
variant="text"
size="small"
startIcon={<CloseIcon/>}
onClick={handleClose}
/>
</>
)}
</div>
<div className="vm-chart-tooltip-data">
<div
className="vm-chart-tooltip-data__marker"
style={{ background: color }}
/>
<p>
{name}:
<b className="vm-chart-tooltip-data__value">{valueFormat}</b>
{unit}
</p>
</div>
{!!fields.length && (
<div className="vm-chart-tooltip-info">
{fields.map((f, i) => (
<div key={`${f}_${i}`}>{f}</div>
))}
</div>
)}
</div>
), targetPortal);
};
export default ChartTooltip;

View file

@ -0,0 +1,80 @@
@use "src/styles/variables" as *;
$chart-tooltip-width: 300px;
$chart-tooltip-icon-width: 25px;
$chart-tooltip-half-icon: calc($chart-tooltip-icon-width/2);
$chart-tooltip-date-width: $chart-tooltip-width - (2*$chart-tooltip-icon-width) - (2*$padding-global) - $padding-small;
$chart-tooltip-x: -1 * ($padding-small + $padding-global + $chart-tooltip-date-width + $chart-tooltip-half-icon);
$chart-tooltip-y: -1 * ($padding-small + $chart-tooltip-half-icon);
.vm-chart-tooltip {
position: absolute;
display: grid;
gap: $padding-global;
width: $chart-tooltip-width;
padding: $padding-small;
border-radius: $border-radius-medium;
background: $color-background-tooltip;
color: $color-white;
font-size: $font-size-small;
font-weight: normal;
line-height: 150%;
word-wrap: break-word;
font-family: $font-family-monospace;
z-index: 98;
user-select: text;
pointer-events: none;
&_sticky {
background-color: $color-dove-gray;
pointer-events: auto;
z-index: 99;
}
&_moved {
position: fixed;
margin-top: $chart-tooltip-y;
margin-left: $chart-tooltip-x;
}
&-header {
display: grid;
grid-template-columns: 1fr $chart-tooltip-icon-width $chart-tooltip-icon-width;
gap: $padding-small;
align-items: center;
justify-content: center;
min-height: 25px;
&__close {
color: $color-white;
}
&__drag {
color: $color-white;
cursor: move;
}
}
&-data {
display: grid;
grid-template-columns: auto 1fr;
gap: $padding-small;
align-items: flex-start;
word-break: break-all;
line-height: 12px;
&__value {
padding: 4px;
font-weight: bold;
}
&__marker {
width: 12px;
height: 12px;
}
}
&-info {
display: grid;
grid-gap: 4px;
}
}

View file

@ -1,9 +1,15 @@
import React, { FC, useCallback, useEffect, useRef, useState } from "preact/compat"; import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from "preact/compat";
import uPlot, { AlignedData as uPlotData, Options as uPlotOptions, Series as uPlotSeries, Range, Scales, Scale } from "uplot"; import uPlot, {
AlignedData as uPlotData,
Options as uPlotOptions,
Series as uPlotSeries,
Range,
Scales,
Scale,
} from "uplot";
import { defaultOptions } from "../../../utils/uplot/helpers"; import { defaultOptions } from "../../../utils/uplot/helpers";
import { dragChart } from "../../../utils/uplot/events"; import { dragChart } from "../../../utils/uplot/events";
import { getAxes, getMinMaxBuffer } from "../../../utils/uplot/axes"; import { getAxes, getMinMaxBuffer } from "../../../utils/uplot/axes";
import { setTooltip } from "../../../utils/uplot/tooltip";
import { MetricResult } from "../../../api/types"; import { MetricResult } from "../../../api/types";
import { limitsDurations } from "../../../utils/time"; import { limitsDurations } from "../../../utils/time";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
@ -13,6 +19,7 @@ import { YaxisState } from "../../../state/graph/reducer";
import "uplot/dist/uPlot.min.css"; import "uplot/dist/uPlot.min.css";
import "./style.scss"; import "./style.scss";
import classNames from "classnames"; import classNames from "classnames";
import ChartTooltip, { ChartTooltipProps } from "../ChartTooltip/ChartTooltip";
export interface LineChartProps { export interface LineChartProps {
metrics: MetricResult[]; metrics: MetricResult[];
@ -24,21 +31,30 @@ export interface LineChartProps {
setPeriod: ({ from, to }: {from: Date, to: Date}) => void; setPeriod: ({ from, to }: {from: Date, to: Date}) => void;
container: HTMLDivElement | null container: HTMLDivElement | null
} }
enum typeChartUpdate {xRange = "xRange", yRange = "yRange", data = "data"} enum typeChartUpdate {xRange = "xRange", yRange = "yRange", data = "data"}
const LineChart: FC<LineChartProps> = ({ data, series, metrics = [], const LineChart: FC<LineChartProps> = ({
period, yaxis, unit, setPeriod, container }) => { data,
series,
metrics = [],
period,
yaxis,
unit,
setPeriod,
container
}) => {
const uPlotRef = useRef<HTMLDivElement>(null); const uPlotRef = useRef<HTMLDivElement>(null);
const [isPanning, setPanning] = useState(false); const [isPanning, setPanning] = useState(false);
const [xRange, setXRange] = useState({ min: period.start, max: period.end }); const [xRange, setXRange] = useState({ min: period.start, max: period.end });
const [uPlotInst, setUPlotInst] = useState<uPlot>(); const [uPlotInst, setUPlotInst] = useState<uPlot>();
const layoutSize = useResize(container); const layoutSize = useResize(container);
const tooltip = document.createElement("div"); const [showTooltip, setShowTooltip] = useState(false);
tooltip.className = "u-tooltip"; const [tooltipIdx, setTooltipIdx] = useState({ seriesIdx: -1, dataIdx: -1 });
const tooltipIdx: {seriesIdx: number | null, dataIdx: number | undefined} = { seriesIdx: null, dataIdx: undefined }; const [tooltipOffset, setTooltipOffset] = useState({ left: 0, top: 0 });
const tooltipOffset = { left: 0, top: 0 }; const [stickyTooltips, setStickyToolTips] = useState<ChartTooltipProps[]>([]);
const tooltipId = useMemo(() => `${tooltipIdx.seriesIdx}_${tooltipIdx.dataIdx}`, [tooltipIdx]);
const setScale = ({ min, max }: { min: number, max: number }): void => { const setScale = ({ min, max }: { min: number, max: number }): void => {
setPeriod({ from: new Date(min * 1000), to: new Date(max * 1000) }); setPeriod({ from: new Date(min * 1000), to: new Date(max * 1000) });
@ -54,12 +70,13 @@ const LineChart: FC<LineChartProps> = ({ data, series, metrics = [],
const onReadyChart = (u: uPlot) => { const onReadyChart = (u: uPlot) => {
const factor = 0.9; const factor = 0.9;
tooltipOffset.left = parseFloat(u.over.style.left); setTooltipOffset({
tooltipOffset.top = parseFloat(u.over.style.top); left: parseFloat(u.over.style.left),
u.root.querySelector(".u-wrap")?.appendChild(tooltip); top: parseFloat(u.over.style.top)
});
u.over.addEventListener("mousedown", e => { u.over.addEventListener("mousedown", e => {
const { ctrlKey, metaKey } = e; const { ctrlKey, metaKey, button } = e;
const leftClick = e.button === 0; const leftClick = button === 0;
const leftClickWithMeta = leftClick && (ctrlKey || metaKey); const leftClickWithMeta = leftClick && (ctrlKey || metaKey);
if (leftClickWithMeta) { if (leftClickWithMeta) {
// drag pan // drag pan
@ -98,21 +115,37 @@ const LineChart: FC<LineChartProps> = ({ data, series, metrics = [],
} }
}; };
const setCursor = (u: uPlot) => { const handleClick = () => {
if (tooltipIdx.dataIdx === u.cursor.idx) return; const id = `${tooltipIdx.seriesIdx}_${tooltipIdx.dataIdx}`;
tooltipIdx.dataIdx = u.cursor.idx || 0; const props = {
if (tooltipIdx.seriesIdx !== null && tooltipIdx.dataIdx !== undefined) { id,
setTooltip({ u, tooltipIdx, metrics, series, tooltip, tooltipOffset, unit }); unit,
series,
metrics,
tooltipIdx,
tooltipOffset,
};
if (!stickyTooltips.find(t => t.id === id)) {
const tooltipProps = JSON.parse(JSON.stringify(props));
setStickyToolTips(prev => [...prev, tooltipProps]);
} }
}; };
const seriesFocus = (u: uPlot, sidx: (number | null)) => { const handleUnStick = (id:string) => {
if (tooltipIdx.seriesIdx === sidx) return; setStickyToolTips(prev => prev.filter(t => t.id !== id));
tooltipIdx.seriesIdx = sidx;
sidx && tooltipIdx.dataIdx !== undefined
? setTooltip({ u, tooltipIdx, metrics, series, tooltip, tooltipOffset, unit })
: tooltip.style.display = "none";
}; };
const setCursor = (u: uPlot) => {
const dataIdx = u.cursor.idx ?? -1;
setTooltipIdx(prev => ({ ...prev, dataIdx }));
};
const seriesFocus = (u: uPlot, sidx: (number | null)) => {
const seriesIdx = sidx ?? -1;
setTooltipIdx(prev => ({ ...prev, seriesIdx }));
};
const getRangeX = (): Range.MinMax => [xRange.min, xRange.max]; const getRangeX = (): Range.MinMax => [xRange.min, xRange.max];
const getRangeY = (u: uPlot, min = 0, max = 1, axis: string): Range.MinMax => { const getRangeY = (u: uPlot, min = 0, max = 1, axis: string): Range.MinMax => {
if (yaxis.limits.enable) return yaxis.limits.range[axis]; if (yaxis.limits.enable) return yaxis.limits.range[axis];
@ -168,6 +201,8 @@ const LineChart: FC<LineChartProps> = ({ data, series, metrics = [],
useEffect(() => setXRange({ min: period.start, max: period.end }), [period]); useEffect(() => setXRange({ min: period.start, max: period.end }), [period]);
useEffect(() => { useEffect(() => {
setStickyToolTips([]);
setTooltipIdx({ seriesIdx: -1, dataIdx: -1 });
if (!uPlotRef.current) return; if (!uPlotRef.current) return;
const u = new uPlot(options, data, uPlotRef.current); const u = new uPlot(options, data, uPlotRef.current);
setUPlotInst(u); setUPlotInst(u);
@ -187,6 +222,17 @@ const LineChart: FC<LineChartProps> = ({ data, series, metrics = [],
useEffect(() => updateChart(typeChartUpdate.xRange), [xRange]); useEffect(() => updateChart(typeChartUpdate.xRange), [xRange]);
useEffect(() => updateChart(typeChartUpdate.yRange), [yaxis]); useEffect(() => updateChart(typeChartUpdate.yRange), [yaxis]);
useEffect(() => {
const show = tooltipIdx.dataIdx !== -1 && tooltipIdx.seriesIdx !== -1;
setShowTooltip(show);
if (show) window.addEventListener("click", handleClick);
return () => {
window.removeEventListener("click", handleClick);
};
}, [tooltipIdx, stickyTooltips]);
return ( return (
<div <div
className={classNames({ className={classNames({
@ -194,7 +240,31 @@ const LineChart: FC<LineChartProps> = ({ data, series, metrics = [],
"vm-line-chart_panning": isPanning "vm-line-chart_panning": isPanning
})} })}
> >
<div ref={uPlotRef}/> <div
className="vm-line-chart__u-plot"
ref={uPlotRef}
/>
{uPlotInst && showTooltip && (
<ChartTooltip
unit={unit}
u={uPlotInst}
series={series}
metrics={metrics}
tooltipIdx={tooltipIdx}
tooltipOffset={tooltipOffset}
id={tooltipId}
/>
)}
{uPlotInst && stickyTooltips.map(t => (
<ChartTooltip
{...t}
isSticky
u={uPlotInst}
key={t.id}
onClose={handleUnStick}
/>
))}
</div> </div>
); );
}; };

View file

@ -7,45 +7,8 @@
&_panning { &_panning {
pointer-events: none; pointer-events: none;
} }
}
.u-tooltip { &__u-plot {
position: absolute; position: relative;
display: none;
grid-gap: $padding-global;
max-width: 300px;
padding: $padding-small;
border-radius: $border-radius-medium;
background: $color-background-tooltip;
color: $color-white;
font-size: $font-size-small;
font-weight: normal;
line-height: 1.4;
word-wrap: break-word;
font-family: monospace;
pointer-events: none;
z-index: 100;
&-data {
display: flex;
flex-wrap: wrap;
align-items: center;
line-height: 150%;
&__value {
padding: 4px;
font-weight: bold;
}
}
&__info {
display: grid;
grid-gap: 4px;
}
&__marker {
width: 12px;
height: 12px;
margin-right: $padding-small;
} }
} }

View file

@ -6,32 +6,42 @@ import Button from "../../Main/Button/Button";
import Modal from "../../Main/Modal/Modal"; import Modal from "../../Main/Modal/Modal";
import "./style.scss"; import "./style.scss";
import Tooltip from "../../Main/Tooltip/Tooltip"; import Tooltip from "../../Main/Tooltip/Tooltip";
import LimitsConfigurator from "./LimitsConfigurator/LimitsConfigurator";
import { SeriesLimits } from "../../../types";
import { useCustomPanelDispatch, useCustomPanelState } from "../../../state/customPanel/CustomPanelStateContext";
import { getAppModeEnable } from "../../../utils/app-mode";
import classNames from "classnames";
const title = "Setting Server URL"; const title = "Settings";
const GlobalSettings: FC = () => { const GlobalSettings: FC = () => {
const { serverUrl } = useAppState(); const appModeEnable = getAppModeEnable();
const { serverUrl: stateServerUrl } = useAppState();
const { seriesLimits } = useCustomPanelState();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const [changedServerUrl, setChangedServerUrl] = useState(serverUrl); const customPanelDispatch = useCustomPanelDispatch();
const setServer = (url?: string) => { const [serverUrl, setServerUrl] = useState(stateServerUrl);
dispatch({ type: "SET_SERVER", payload: url || changedServerUrl }); const [limits, setLimits] = useState<SeriesLimits>(seriesLimits);
handleClose();
};
const createSetServer = () => () => {
setServer();
};
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true); const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false); const handleClose = () => setOpen(false);
const handlerApply = () => {
dispatch({ type: "SET_SERVER", payload: serverUrl });
customPanelDispatch({ type: "SET_SERIES_LIMITS", payload: limits });
handleClose();
};
return <> return <>
<Tooltip title={title}> <Tooltip title={title}>
<Button <Button
className="vm-header-button" className={classNames({
"vm-header-button": !appModeEnable
})}
variant="contained" variant="contained"
color="primary" color="primary"
startIcon={<SettingsIcon/>} startIcon={<SettingsIcon/>}
@ -44,10 +54,20 @@ const GlobalSettings: FC = () => {
onClose={handleClose} onClose={handleClose}
> >
<div className="vm-server-configurator"> <div className="vm-server-configurator">
{!appModeEnable && (
<div className="vm-server-configurator__input">
<ServerConfigurator
serverUrl={serverUrl}
onChange={setServerUrl}
onEnter={handlerApply}
/>
</div>
)}
<div className="vm-server-configurator__input"> <div className="vm-server-configurator__input">
<ServerConfigurator <LimitsConfigurator
setServer={setChangedServerUrl} limits={limits}
onEnter={setServer} onChange={setLimits}
onEnter={handlerApply}
/> />
</div> </div>
<div className="vm-server-configurator__footer"> <div className="vm-server-configurator__footer">
@ -60,7 +80,7 @@ const GlobalSettings: FC = () => {
</Button> </Button>
<Button <Button
variant="contained" variant="contained"
onClick={createSetServer()} onClick={handlerApply}
> >
apply apply
</Button> </Button>

View file

@ -0,0 +1,88 @@
import React, { FC, useState } from "preact/compat";
import { DisplayType, ErrorTypes, SeriesLimits } from "../../../../types";
import TextField from "../../../Main/TextField/TextField";
import Tooltip from "../../../Main/Tooltip/Tooltip";
import { InfoIcon, RestartIcon } from "../../../Main/Icons";
import Button from "../../../Main/Button/Button";
import { DEFAULT_MAX_SERIES } from "../../../../constants/graph";
import "./style.scss";
export interface ServerConfiguratorProps {
limits: SeriesLimits
onChange: (limits: SeriesLimits) => void
onEnter: () => void
}
const fields: {label: string, type: DisplayType}[] = [
{ label: "Graph", type: "chart" },
{ label: "JSON", type: "code" },
{ label: "Table", type: "table" }
];
const LimitsConfigurator: FC<ServerConfiguratorProps> = ({ limits, onChange , onEnter }) => {
const [error, setError] = useState({
table: "",
chart: "",
code: ""
});
const handleChange = (val: string, type: DisplayType) => {
const value = val || "";
setError(prev => ({ ...prev, [type]: +value < 0 ? ErrorTypes.positiveNumber : "" }));
onChange({
...limits,
[type]: !value ? Infinity : value
});
};
const handleReset = () => {
onChange(DEFAULT_MAX_SERIES);
};
const createChangeHandler = (type: DisplayType) => (val: string) => {
handleChange(val, type);
};
return (
<div className="vm-limits-configurator">
<div className="vm-limits-configurator-title">
Series limits by tabs
<Tooltip title="To disable limits set to 0">
<Button
variant="text"
color="primary"
size="small"
startIcon={<InfoIcon/>}
/>
</Tooltip>
<div className="vm-limits-configurator-title__reset">
<Button
variant="text"
color="primary"
size="small"
startIcon={<RestartIcon/>}
onClick={handleReset}
>
Reset
</Button>
</div>
</div>
<div className="vm-limits-configurator__inputs">
{fields.map(f => (
<TextField
key={f.type}
label={f.label}
value={limits[f.type]}
error={error[f.type]}
onChange={createChangeHandler(f.type)}
onEnter={onEnter}
type="number"
/>
))}
</div>
</div>
);
};
export default LimitsConfigurator;

View file

@ -0,0 +1,28 @@
@use "src/styles/variables" as *;
.vm-limits-configurator {
&-title {
display: flex;
align-items: center;
justify-content: flex-start;
font-size: $font-size;
font-weight: bold;
margin-bottom: $padding-global;
&__reset {
display: flex;
align-items: center;
justify-content: flex-end;
flex-grow: 1;
}
}
&__inputs {
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: center;
justify-content: space-between;
gap: $padding-global;
}
}

View file

@ -1,41 +1,34 @@
import React, { FC, useState } from "preact/compat"; import React, { FC, useState } from "preact/compat";
import { useAppState } from "../../../../state/common/StateContext";
import { ErrorTypes } from "../../../../types"; import { ErrorTypes } from "../../../../types";
import TextField from "../../../Main/TextField/TextField"; import TextField from "../../../Main/TextField/TextField";
import { isValidHttpUrl } from "../../../../utils/url"; import { isValidHttpUrl } from "../../../../utils/url";
export interface ServerConfiguratorProps { export interface ServerConfiguratorProps {
setServer: (url: string) => void serverUrl: string
onEnter: (url: string) => void onChange: (url: string) => void
onEnter: () => void
} }
const ServerConfigurator: FC<ServerConfiguratorProps> = ({ setServer , onEnter }) => { const ServerConfigurator: FC<ServerConfiguratorProps> = ({ serverUrl, onChange , onEnter }) => {
const { serverUrl } = useAppState();
const [error, setError] = useState(""); const [error, setError] = useState("");
const [changedServerUrl, setChangedServerUrl] = useState(serverUrl);
const onChangeServer = (val: string) => { const onChangeServer = (val: string) => {
const value = val || ""; const value = val || "";
setChangedServerUrl(value); onChange(value);
setServer(value);
setError(""); setError("");
if (!value) setError(ErrorTypes.emptyServer); if (!value) setError(ErrorTypes.emptyServer);
if (!isValidHttpUrl(value)) setError(ErrorTypes.validServer); if (!isValidHttpUrl(value)) setError(ErrorTypes.validServer);
}; };
const handleEnter = () => {
onEnter(changedServerUrl);
};
return ( return (
<TextField <TextField
autofocus autofocus
label="Server URL" label="Server URL"
value={changedServerUrl} value={serverUrl}
error={error} error={error}
onChange={onChangeServer} onChange={onChangeServer}
onEnter={handleEnter} onEnter={onEnter}
/> />
); );
}; };

View file

@ -3,7 +3,7 @@
.vm-server-configurator { .vm-server-configurator {
display: grid; display: grid;
align-items: center; align-items: center;
gap: $padding-global; gap: $padding-medium;
width: 600px; width: 600px;
&__input { &__input {

View file

@ -1,11 +1,9 @@
import React, { FC, useEffect, useMemo, useRef, useState } from "preact/compat"; import React, { FC, useRef } from "preact/compat";
import { KeyboardEvent } from "react"; import { KeyboardEvent } from "react";
import { ErrorTypes } from "../../../types"; import { ErrorTypes } from "../../../types";
import TextField from "../../Main/TextField/TextField"; import TextField from "../../Main/TextField/TextField";
import Popper from "../../Main/Popper/Popper"; import Autocomplete from "../../Main/Autocomplete/Autocomplete";
import useClickOutside from "../../../hooks/useClickOutside";
import "./style.scss"; import "./style.scss";
import classNames from "classnames";
export interface QueryEditorProps { export interface QueryEditorProps {
onChange: (query: string) => void; onChange: (query: string) => void;
@ -18,7 +16,7 @@ export interface QueryEditorProps {
error?: ErrorTypes | string; error?: ErrorTypes | string;
options: string[]; options: string[];
label: string; label: string;
size?: "small" | "medium" | undefined; disabled?: boolean
} }
const QueryEditor: FC<QueryEditorProps> = ({ const QueryEditor: FC<QueryEditorProps> = ({
@ -31,25 +29,14 @@ const QueryEditor: FC<QueryEditorProps> = ({
error, error,
options, options,
label, label,
disabled = false
}) => { }) => {
const [focusOption, setFocusOption] = useState(-1);
const [openAutocomplete, setOpenAutocomplete] = useState(false);
const autocompleteAnchorEl = useRef<HTMLDivElement>(null); const autocompleteAnchorEl = useRef<HTMLDivElement>(null);
const wrapperEl = useRef<HTMLDivElement>(null);
const foundOptions = useMemo(() => { const handleSelect = (val: string) => {
setFocusOption(0); onChange(val);
if (!openAutocomplete) return []; };
try {
const regexp = new RegExp(String(value), "i");
const found = options.filter((item) => regexp.test(item) && (item !== value));
return found.sort((a,b) => (a.match(regexp)?.index || 0) - (b.match(regexp)?.index || 0));
} catch (e) {
return [];
}
}, [openAutocomplete, options]);
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
const { key, ctrlKey, metaKey, shiftKey } = e; const { key, ctrlKey, metaKey, shiftKey } = e;
@ -59,62 +46,24 @@ const QueryEditor: FC<QueryEditorProps> = ({
const arrowDown = key === "ArrowDown"; const arrowDown = key === "ArrowDown";
const enter = key === "Enter"; const enter = key === "Enter";
const hasAutocomplete = openAutocomplete && foundOptions.length; // prev value from history
if (arrowUp && ctrlMetaKey) {
const isArrows = arrowUp || arrowDown;
const arrowsByOptions = isArrows && hasAutocomplete;
const arrowsByHistory = isArrows && ctrlMetaKey;
const enterByOptions = enter && hasAutocomplete;
if (arrowsByOptions || arrowsByHistory || enterByOptions) {
e.preventDefault(); e.preventDefault();
}
// ArrowUp
if (arrowUp && hasAutocomplete && !ctrlMetaKey) {
setFocusOption((prev) => prev === 0 ? 0 : prev - 1);
} else if (arrowUp && ctrlMetaKey) {
onArrowUp(); onArrowUp();
} }
// ArrowDown // next value from history
if (arrowDown && hasAutocomplete && !ctrlMetaKey) { if (arrowDown && ctrlMetaKey) {
setFocusOption((prev) => prev >= foundOptions.length - 1 ? foundOptions.length - 1 : prev + 1); e.preventDefault();
} else if (arrowDown && ctrlMetaKey) {
onArrowDown(); onArrowDown();
} }
// Enter // execute query
if (enter && hasAutocomplete && !shiftKey && !ctrlMetaKey) { if (enter && !shiftKey) {
onChange(foundOptions[focusOption]);
setOpenAutocomplete(false);
} else if (enter && !shiftKey) {
onEnter(); onEnter();
} }
}; };
const handleCloseAutocomplete = () => {
setOpenAutocomplete(false);
};
const createHandlerOnChangeAutocomplete = (item: string) => () => {
onChange(item);
handleCloseAutocomplete();
};
useEffect(() => {
const words = (value.match(/[a-zA-Z_:.][a-zA-Z0-9_:.]*/gm) || []).length;
setOpenAutocomplete(autocomplete && value.length > 2 && words <= 1);
}, [autocomplete, value]);
useEffect(() => {
if (!wrapperEl.current) return;
const target = wrapperEl.current.childNodes[focusOption] as HTMLElement;
if (target?.scrollIntoView) target.scrollIntoView({ block: "center" });
}, [focusOption]);
useClickOutside(autocompleteAnchorEl, () => setOpenAutocomplete(false), wrapperEl);
return <div return <div
className="vm-query-editor" className="vm-query-editor"
ref={autocompleteAnchorEl} ref={autocompleteAnchorEl}
@ -127,31 +76,16 @@ const QueryEditor: FC<QueryEditorProps> = ({
error={error} error={error}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onChange={onChange} onChange={onChange}
disabled={disabled}
/> />
<Popper {autocomplete && (
open={openAutocomplete} <Autocomplete
buttonRef={autocompleteAnchorEl} value={value}
placement="bottom-left" options={options}
onClose={handleCloseAutocomplete} anchor={autocompleteAnchorEl}
> onSelect={handleSelect}
<div />
className="vm-query-editor-autocomplete" )}
ref={wrapperEl}
>
{foundOptions.map((item, i) =>
<div
className={classNames({
"vm-list__item": true,
"vm-list__item_active": i === focusOption
})}
id={`$autocomplete$${item}`}
key={item}
onClick={createHandlerOnChangeAutocomplete(item)}
>
{item}
</div>)}
</div>
</Popper>
</div>; </div>;
}; };

View file

@ -43,6 +43,10 @@ const Header: FC = () => {
{ {
label: "Top queries", label: "Top queries",
value: router.topQueries, value: router.topQueries,
},
{
label: "Trace analyzer",
value: router.trace,
} }
]), [appModeEnable]); ]), [appModeEnable]);
@ -111,7 +115,7 @@ const Header: FC = () => {
{headerSetup?.timeSelector && <TimeSelector/>} {headerSetup?.timeSelector && <TimeSelector/>}
{headerSetup?.cardinalityDatePicker && <CardinalityDatePicker/>} {headerSetup?.cardinalityDatePicker && <CardinalityDatePicker/>}
{headerSetup?.executionControls && <ExecutionControls/>} {headerSetup?.executionControls && <ExecutionControls/>}
{headerSetup?.globalSettings && !appModeEnable && <GlobalSettings/>} <GlobalSettings/>
<ShortcutKeys/> <ShortcutKeys/>
</div> </div>
</header>; </header>;

View file

@ -1,8 +1,8 @@
import React, { FC } from "preact/compat"; import React, { FC } from "preact/compat";
import { ReactNode } from "react"; import { ReactNode } from "react";
import classNames from "classnames"; import classNames from "classnames";
import "./style.scss";
import { ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from "../Icons"; import { ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from "../Icons";
import "./style.scss";
interface AlertProps { interface AlertProps {
variant?: "success" | "error" | "info" | "warning" variant?: "success" | "error" | "info" | "warning"

View file

@ -13,7 +13,7 @@
font-size: $font-size-medium; font-size: $font-size-medium;
font-weight: 500; font-weight: 500;
color: $color-text; color: $color-text;
line-height: 1.3; line-height: 20px;
&:after { &:after {
position: absolute; position: absolute;
@ -41,6 +41,7 @@
&__content { &__content {
filter: brightness(0.6); filter: brightness(0.6);
white-space: pre-line;
} }
&_success { &_success {

View file

@ -0,0 +1,132 @@
import React, { FC, Ref, useEffect, useMemo, useRef, useState } from "preact/compat";
import classNames from "classnames";
import useClickOutside from "../../../hooks/useClickOutside";
import Popper from "../Popper/Popper";
import "./style.scss";
interface AutocompleteProps {
value: string
options: string[]
anchor: Ref<HTMLElement>
disabled?: boolean
maxWords?: number
onSelect: (val: string) => void
}
const Autocomplete: FC<AutocompleteProps> = ({
value,
options,
anchor,
disabled,
maxWords = 1,
onSelect,
}) => {
const wrapperEl = useRef<HTMLDivElement>(null);
const [openAutocomplete, setOpenAutocomplete] = useState(false);
const [focusOption, setFocusOption] = useState(-1);
const foundOptions = useMemo(() => {
if (!openAutocomplete) return [];
try {
const regexp = new RegExp(String(value), "i");
const found = options.filter((item) => regexp.test(item) && (item !== value));
return found.sort((a,b) => (a.match(regexp)?.index || 0) - (b.match(regexp)?.index || 0));
} catch (e) {
return [];
}
}, [openAutocomplete, options, value]);
const handleCloseAutocomplete = () => {
setOpenAutocomplete(false);
};
const createHandlerSelect = (item: string) => () => {
if (disabled) return;
onSelect(item);
handleCloseAutocomplete();
};
const scrollToValue = () => {
if (!wrapperEl.current) return;
const target = wrapperEl.current.childNodes[focusOption] as HTMLElement;
if (target?.scrollIntoView) target.scrollIntoView({ block: "center" });
};
const handleKeyDown = (e: KeyboardEvent) => {
const { key, ctrlKey, metaKey, shiftKey } = e;
const modifiers = ctrlKey || metaKey || shiftKey;
if (key === "ArrowUp" && !modifiers) {
e.preventDefault();
setFocusOption((prev) => prev <= 0 ? 0 : prev - 1);
}
if (key === "ArrowDown" && !modifiers) {
e.preventDefault();
const lastIndex = foundOptions.length - 1;
setFocusOption((prev) => prev >= lastIndex ? lastIndex : prev + 1);
}
if (key === "Enter") {
const value = foundOptions[focusOption];
value && onSelect(value);
handleCloseAutocomplete();
}
if (key === "Escape") {
handleCloseAutocomplete();
}
};
useEffect(() => {
const words = (value.match(/[a-zA-Z_:.][a-zA-Z0-9_:.]*/gm) || []).length;
setOpenAutocomplete(value.length > 2 && words <= maxWords);
}, [value]);
useEffect(() => {
scrollToValue();
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [focusOption, foundOptions]);
useEffect(() => {
setFocusOption(-1);
}, [foundOptions]);
useClickOutside(wrapperEl, handleCloseAutocomplete);
return (
<Popper
open={openAutocomplete}
buttonRef={anchor}
placement="bottom-left"
onClose={handleCloseAutocomplete}
>
<div
className="vm-autocomplete"
ref={wrapperEl}
>
{foundOptions.map((option, i) =>
<div
className={classNames({
"vm-list__item": true,
"vm-list__item_active": i === focusOption
})}
id={`$autocomplete$${option}`}
key={option}
onClick={createHandlerSelect(option)}
>
{option}
</div>
)}
</div>
</Popper>
);
};
export default Autocomplete;

View file

@ -0,0 +1,6 @@
@use "src/styles/variables" as *;
.vm-autocomplete {
max-height: 300px;
overflow: auto;
}

View file

@ -5,7 +5,7 @@ import "./style.scss";
interface ButtonProps { interface ButtonProps {
variant?: "contained" | "outlined" | "text" variant?: "contained" | "outlined" | "text"
color?: "primary" | "secondary" | "success" | "error" color?: "primary" | "secondary" | "success" | "error" | "gray" | "warning"
size?: "small" | "medium" | "large" size?: "small" | "medium" | "large"
endIcon?: ReactNode endIcon?: ReactNode
startIcon?: ReactNode startIcon?: ReactNode
@ -14,6 +14,7 @@ interface ButtonProps {
children?: ReactNode children?: ReactNode
className?: string className?: string
onClick?: (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void onClick?: (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void
onMouseDown?: (e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void
} }
const Button: FC<ButtonProps> = ({ const Button: FC<ButtonProps> = ({
@ -27,6 +28,7 @@ const Button: FC<ButtonProps> = ({
className, className,
disabled, disabled,
onClick, onClick,
onMouseDown,
}) => { }) => {
const classesButton = classNames({ const classesButton = classNames({
@ -45,6 +47,7 @@ const Button: FC<ButtonProps> = ({
className={classesButton} className={classesButton}
disabled={disabled} disabled={disabled}
onClick={onClick} onClick={onClick}
onMouseDown={onMouseDown}
> >
<> <>
{startIcon && <span className="vm-button__start-icon">{startIcon}</span>} {startIcon && <span className="vm-button__start-icon">{startIcon}</span>}

View file

@ -135,6 +135,23 @@ $button-radius: 6px;
} }
} }
&_contained_gray {
color: $color-text-secondary;
&:before {
background-color: $color-text-secondary;
}
}
&_contained_warning {
color: $color-warning;
&:before {
background-color: $color-warning;
opacity: 0.2;
}
}
/* variant TEXT */ /* variant TEXT */
&_text_primary { &_text_primary {
@ -153,6 +170,14 @@ $button-radius: 6px;
color: $color-error; color: $color-error;
} }
&_text_gray {
color: $color-text-secondary;
}
&_text_warning {
color: $color-warning;
}
/* variant OUTLINED */ /* variant OUTLINED */
&_outlined_primary { &_outlined_primary {
@ -174,4 +199,14 @@ $button-radius: 6px;
border: 1px solid $color-success; border: 1px solid $color-success;
color: $color-success; color: $color-success;
} }
&_outlined_gray {
border: 1px solid $color-text-secondary;
color: $color-text-secondary;
}
&_outlined_warning {
border: 1px solid $color-warning;
color: $color-warning;
}
} }

View file

@ -267,3 +267,45 @@ export const DoneIcon = () => (
/> />
</svg> </svg>
); );
export const VisibilityIcon = () => (
<svg
viewBox="0 0 24 24"
fill="currentColor"
>
<path
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
></path>
</svg>
);
export const VisibilityOffIcon = () => (
<svg
viewBox="0 0 24 24"
fill="currentColor"
>
<path
d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78 3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"
></path>
</svg>
);
export const CopyIcon = () => (
<svg
viewBox="0 0 24 24"
fill="currentColor"
>
<path
d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"
></path>
</svg>
);
export const DragIcon = () => (
<svg
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"></path>
</svg>
);

View file

@ -16,11 +16,9 @@ $padding-modal: 22px;
&-content { &-content {
padding: $padding-modal; padding: $padding-modal;
max-height: 85vh;
background: $color-white; background: $color-white;
box-shadow: 0 0 24px rgba($color-black, 0.07); box-shadow: 0 0 24px rgba($color-black, 0.07);
border-radius: $border-radius-small; border-radius: $border-radius-small;
overflow: hidden;
&-header { &-header {
display: grid; display: grid;

View file

@ -64,7 +64,10 @@ const TextField: FC<TextFieldProps> = ({
}, [fieldRef, autofocus]); }, [fieldRef, autofocus]);
return <label return <label
className="vm-text-field" className={classNames({
"vm-text-field": true,
"vm-text-field_textarea": type === "textarea",
})}
data-replicated-value={value} data-replicated-value={value}
> >
{startIcon && <div className="vm-text-field__icon-start">{startIcon}</div>} {startIcon && <div className="vm-text-field__icon-start">{startIcon}</div>}

View file

@ -6,7 +6,7 @@
margin: 6px 0; margin: 6px 0;
width: 100%; width: 100%;
&::after { &_textarea:after {
content: attr(data-replicated-value) " "; content: attr(data-replicated-value) " ";
white-space: pre-wrap; white-space: pre-wrap;
visibility: hidden; visibility: hidden;
@ -29,6 +29,7 @@
&__helper-text, { &__helper-text, {
position: absolute; position: absolute;
left: calc($padding-global/2); left: calc($padding-global/2);
max-width: calc(100% - $padding-global);
padding: 0 3px; padding: 0 3px;
font-size: $font-size-small; font-size: $font-size-small;
line-height: $font-size-small; line-height: $font-size-small;
@ -36,6 +37,12 @@
user-select: none; user-select: none;
background-color: $color-background-block; background-color: $color-background-block;
z-index: 2; z-index: 2;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* number of lines to show */
line-clamp: 2;
-webkit-box-orient: vertical;
} }
&__label { &__label {
@ -44,7 +51,7 @@
} }
&__error { &__error {
bottom: calc($font-size-small/-2); top: calc(100% - ($font-size-small/2));
color: $color-error; color: $color-error;
} }

View file

@ -3,12 +3,14 @@ import { TracingData } from "../../api/types";
let traceId = 0; let traceId = 0;
export default class Trace { export default class Trace {
private readonly tracing: TracingData; private tracing: TracingData;
private readonly tracingChildren: Trace[]; private query: string;
private readonly query: string; private tracingChildren: Trace[];
private readonly originalTracing: TracingData;
private readonly id: number; private readonly id: number;
constructor(tracingData: TracingData, query: string) { constructor(tracingData: TracingData, query: string) {
this.tracing = tracingData; this.tracing = tracingData;
this.originalTracing = JSON.parse(JSON.stringify(tracingData));
this.query = query; this.query = query;
this.id = traceId++; this.id = traceId++;
const children = tracingData.children || []; const children = tracingData.children || [];
@ -30,4 +32,21 @@ export default class Trace {
get duration(): number { get duration(): number {
return this.tracing.duration_msec; return this.tracing.duration_msec;
} }
get JSON(): string {
return JSON.stringify(this.tracing, null, 2);
}
get originalJSON(): string {
return JSON.stringify(this.originalTracing, null, 2);
}
setTracing (tracingData: TracingData) {
this.tracing = tracingData;
const children = tracingData.children || [];
this.tracingChildren = children.map((x: TracingData) => new Trace(x, this.query));
}
setQuery (query: string) {
this.query = query;
}
resetTracing () {
this.tracing = this.originalTracing;
}
} }

View file

@ -1,18 +1,38 @@
import React, { FC } from "preact/compat"; import React, { FC, useState } from "preact/compat";
import Trace from "./Trace"; import Trace from "./Trace";
import Button from "../Main/Button/Button"; import Button from "../Main/Button/Button";
import { DeleteIcon } from "../Main/Icons"; import { CodeIcon, DeleteIcon } from "../Main/Icons";
import "./style.scss"; import "./style.scss";
import NestedNav from "./NestedNav/NestedNav"; import NestedNav from "./NestedNav/NestedNav";
import Alert from "../Main/Alert/Alert"; import Alert from "../Main/Alert/Alert";
import Tooltip from "../Main/Tooltip/Tooltip"; import Tooltip from "../Main/Tooltip/Tooltip";
import Modal from "../Main/Modal/Modal";
import JsonForm from "../../pages/TracePage/JsonForm/JsonForm";
interface TraceViewProps { interface TraceViewProps {
traces: Trace[]; traces: Trace[];
jsonEditor?: boolean;
onDeleteClick: (trace: Trace) => void; onDeleteClick: (trace: Trace) => void;
} }
const TracingsView: FC<TraceViewProps> = ({ traces, onDeleteClick }) => { const TracingsView: FC<TraceViewProps> = ({ traces, jsonEditor = false, onDeleteClick }) => {
const [openTrace, setOpenTrace] = useState<Trace | null>(null);
const handleCloseJson = () => {
setOpenTrace(null);
};
const handleUpdateTrace = (val: string, title: string) => {
if (!jsonEditor || !openTrace) return;
try {
openTrace.setTracing(JSON.parse(val));
openTrace.setQuery(title);
setOpenTrace(null);
} catch (e) {
console.error(e);
}
};
if (!traces.length) { if (!traces.length) {
return ( return (
<Alert variant="info"> <Alert variant="info">
@ -25,34 +45,66 @@ const TracingsView: FC<TraceViewProps> = ({ traces, onDeleteClick }) => {
onDeleteClick(tracingData); onDeleteClick(tracingData);
}; };
return <div className="vm-tracings-view"> const handleJsonClick = (tracingData: Trace) => () => {
{traces.map((trace: Trace) => ( setOpenTrace(tracingData);
<div };
className="vm-tracings-view-trace vm-block vm-block_empty-padding"
key={trace.idValue} return (
> <>
<div className="vm-tracings-view-trace-header"> <div className="vm-tracings-view">
<h3 className="vm-tracings-view-trace-header-title"> {traces.map((trace: Trace) => (
Trace for <b className="vm-tracings-view-trace-header-title__query">{trace.queryValue}</b> <div
</h3> className="vm-tracings-view-trace vm-block vm-block_empty-padding"
<Tooltip title={"Remove trace"}> key={trace.idValue}
<Button >
variant="text" <div className="vm-tracings-view-trace-header">
color="error" <h3 className="vm-tracings-view-trace-header-title">
startIcon={<DeleteIcon/>} Trace for <b className="vm-tracings-view-trace-header-title__query">{trace.queryValue}</b>
onClick={handleDeleteClick(trace)} </h3>
/> <Tooltip title={"Open JSON"}>
</Tooltip> <Button
</div> variant="text"
<nav className="vm-tracings-view-trace__nav"> startIcon={<CodeIcon/>}
<NestedNav onClick={handleJsonClick(trace)}
trace={trace} />
totalMsec={trace.duration} </Tooltip>
/> <Tooltip title={"Remove trace"}>
</nav> <Button
variant="text"
color="error"
startIcon={<DeleteIcon/>}
onClick={handleDeleteClick(trace)}
/>
</Tooltip>
</div>
<nav className="vm-tracings-view-trace__nav">
<NestedNav
trace={trace}
totalMsec={trace.duration}
/>
</nav>
</div>
))}
</div> </div>
))}
</div>; {openTrace && (
<Modal
title={openTrace.queryValue}
onClose={handleCloseJson}
>
<JsonForm
editable={jsonEditor}
displayTitle={jsonEditor}
defaultTile={openTrace.queryValue}
defaultJson={openTrace.JSON}
resetValue={openTrace.originalJSON}
onClose={handleCloseJson}
onUpload={handleUpdateTrace}
/>
</Modal>
)}
</>
);
}; };
export default TracingsView; export default TracingsView;

View file

@ -13,6 +13,7 @@
padding: $padding-small $padding-small $padding-small $padding-medium; padding: $padding-small $padding-small $padding-small $padding-medium;
&-title { &-title {
flex-grow: 1;
font-size: $font-size-medium; font-size: $font-size-medium;
margin-right: $padding-small; margin-right: $padding-small;

View file

@ -24,7 +24,6 @@ const JsonView: FC<JsonViewProps> = ({ data }) => {
<div className="vm-json-view__copy"> <div className="vm-json-view__copy">
<Button <Button
variant="outlined" variant="outlined"
fullWidth={false}
onClick={handlerCopy} onClick={handlerCopy}
> >
Copy JSON Copy JSON

View file

@ -1,10 +1,17 @@
import React, { FC, useMemo, useState } from "preact/compat"; import React, { FC, useEffect, useMemo, useRef, useState } from "preact/compat";
import { InstantMetricResult } from "../../../api/types"; import { InstantMetricResult } from "../../../api/types";
import { InstantDataSeries } from "../../../types"; import { InstantDataSeries } from "../../../types";
import { useSortedCategories } from "../../../hooks/useSortedCategories"; import { useSortedCategories } from "../../../hooks/useSortedCategories";
import Alert from "../../Main/Alert/Alert"; import Alert from "../../Main/Alert/Alert";
import classNames from "classnames"; import classNames from "classnames";
import { ArrowDropDownIcon } from "../../Main/Icons"; import { ArrowDropDownIcon, CopyIcon } from "../../Main/Icons";
import Tooltip from "../../Main/Tooltip/Tooltip";
import Button from "../../Main/Button/Button";
import { useSnack } from "../../../contexts/Snackbar";
import { getNameForMetric } from "../../../utils/metric";
import { useCustomPanelState } from "../../../state/customPanel/CustomPanelStateContext";
import "./style.scss";
import useResize from "../../../hooks/useResize";
export interface GraphViewProps { export interface GraphViewProps {
data: InstantMetricResult[]; data: InstantMetricResult[];
@ -12,106 +19,183 @@ export interface GraphViewProps {
} }
const TableView: FC<GraphViewProps> = ({ data, displayColumns }) => { const TableView: FC<GraphViewProps> = ({ data, displayColumns }) => {
const { showInfoMessage } = useSnack();
const sortedColumns = useSortedCategories(data, displayColumns); const { tableCompact } = useCustomPanelState();
const windowSize = useResize(document.body);
const tableRef = useRef<HTMLTableElement>(null);
const [tableTop, setTableTop] = useState(0);
const [headTop, setHeadTop] = useState(0);
const [orderBy, setOrderBy] = useState(""); const [orderBy, setOrderBy] = useState("");
const [orderDir, setOrderDir] = useState<"asc" | "desc">("asc"); const [orderDir, setOrderDir] = useState<"asc" | "desc">("asc");
const sortedColumns = (tableCompact
? useSortedCategories([{ group: 0, metric: { "Data": "Data" } }], ["Data"])
: useSortedCategories(data, displayColumns)
);
const getCopyValue = (metric: { [p: string]: string }) => {
const { __name__, ...fields } = metric;
if (!__name__ && !Object.keys(fields).length) return "";
return `${__name__} ${JSON.stringify(fields)}`;
};
const rows: InstantDataSeries[] = useMemo(() => { const rows: InstantDataSeries[] = useMemo(() => {
const rows = data?.map(d => ({ const rows = data?.map(d => ({
metadata: sortedColumns.map(c => d.metric[c.key] || "-"), metadata: sortedColumns.map(c => (tableCompact
value: d.value ? d.value[1] : "-" ? getNameForMetric(d, undefined, "=", true)
: (d.metric[c.key] || "-")
)),
value: d.value ? d.value[1] : "-",
copyValue: getCopyValue(d.metric)
})); }));
const orderByValue = orderBy === "Value"; const orderByValue = orderBy === "Value";
const rowIndex = sortedColumns.findIndex(c => c.key === orderBy); const rowIndex = sortedColumns.findIndex(c => c.key === orderBy);
if (!orderByValue && rowIndex === -1) return rows; if (!orderByValue && rowIndex === -1) return rows;
return rows.sort((a,b) => { return rows.sort((a, b) => {
const n1 = orderByValue ? Number(a.value) : a.metadata[rowIndex]; const n1 = orderByValue ? Number(a.value) : a.metadata[rowIndex];
const n2 = orderByValue ? Number(b.value) : b.metadata[rowIndex]; const n2 = orderByValue ? Number(b.value) : b.metadata[rowIndex];
const asc = orderDir === "asc" ? n1 < n2 : n1 > n2; const asc = orderDir === "asc" ? n1 < n2 : n1 > n2;
return asc ? -1 : 1; return asc ? -1 : 1;
}); });
}, [sortedColumns, data, orderBy, orderDir]); }, [sortedColumns, data, orderBy, orderDir, tableCompact]);
const createSortHandler = (key: string) => () => { const hasCopyValue = useMemo(() => rows.some(r => r.copyValue), [rows]);
sortHandler(key);
};
const sortHandler = (key: string) => { const sortHandler = (key: string) => {
setOrderDir((prev) => prev === "asc" && orderBy === key ? "desc" : "asc"); setOrderDir((prev) => prev === "asc" && orderBy === key ? "desc" : "asc");
setOrderBy(key); setOrderBy(key);
}; };
const copyHandler = async (copyValue: string) => {
await navigator.clipboard.writeText(copyValue);
showInfoMessage({ text: "Row has been copied", type: "success" });
};
const createSortHandler = (key: string) => () => {
sortHandler(key);
};
const createCopyHandler = (copyValue: string) => () => {
copyHandler(copyValue);
};
const handleScroll = () => {
if (!tableRef.current) return;
const { top } = tableRef.current.getBoundingClientRect();
setHeadTop(top < 0 ? window.scrollY - tableTop : 0);
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [tableRef, tableTop, windowSize]);
useEffect(() => {
if (!tableRef.current) return;
const { top } = tableRef.current.getBoundingClientRect();
setTableTop(top + window.scrollY);
}, [tableRef, windowSize]);
if (!rows.length) return <Alert variant="warning">No data to show</Alert>; if (!rows.length) return <Alert variant="warning">No data to show</Alert>;
return ( return (
<table className="vm-table"> <div className="vm-table-view">
<thead className="vm-table-header"> <table
<tr className="vm-table__row vm-table__row_header"> className="vm-table"
{sortedColumns.map((col, index) => ( ref={tableRef}
>
<thead className="vm-table-header">
<tr
className="vm-table__row vm-table__row_header"
style={{ transform: `translateY(${headTop}px)` }}
>
{sortedColumns.map((col, index) => (
<td
className="vm-table-cell vm-table-cell_header vm-table-cell_sort"
key={index}
onClick={createSortHandler(col.key)}
>
<div className="vm-table-cell__content">
{col.key}
<div
className={classNames({
"vm-table__sort-icon": true,
"vm-table__sort-icon_active": orderBy === col.key,
"vm-table__sort-icon_desc": orderDir === "desc" && orderBy === col.key
})}
>
<ArrowDropDownIcon/>
</div>
</div>
</td>
))}
<td <td
className="vm-table-cell vm-table-cell_header vm-table-cell_sort" className="vm-table-cell vm-table-cell_header vm-table-cell_right vm-table-cell_sort"
key={index} onClick={createSortHandler("Value")}
onClick={createSortHandler(col.key)}
> >
<div className="vm-table-cell__content"> <div className="vm-table-cell__content">
{col.key}
<div <div
className={classNames({ className={classNames({
"vm-table__sort-icon": true, "vm-table__sort-icon": true,
"vm-table__sort-icon_active": orderBy === col.key, "vm-table__sort-icon_active": orderBy === "Value",
"vm-table__sort-icon_desc": orderDir === "desc" && orderBy === col.key "vm-table__sort-icon_desc": orderDir === "desc"
})} })}
> >
<ArrowDropDownIcon/> <ArrowDropDownIcon/>
</div> </div>
Value
</div> </div>
</td> </td>
))} {hasCopyValue && <td className="vm-table-cell vm-table-cell_header"/>}
<td
className="vm-table-cell vm-table-cell_header vm-table-cell_right vm-table-cell_sort"
onClick={createSortHandler("Value")}
>
<div className="vm-table-cell__content">
<div
className={classNames({
"vm-table__sort-icon": true,
"vm-table__sort-icon_active": orderBy === "Value",
"vm-table__sort-icon_desc": orderDir === "desc"
})}
>
<ArrowDropDownIcon/>
</div>
Value
</div>
</td>
</tr>
</thead>
<tbody className="vm-table-body">
{rows.map((row, index) => (
<tr
className="vm-table__row"
key={index}
>
{row.metadata.map((rowMeta, index2) => (
<td
className={classNames({
"vm-table-cell vm-table-cell_no-wrap": true,
"vm-table-cell_gray": rows[index - 1] && rows[index - 1].metadata[index2] === rowMeta
})}
key={index2}
>
{rowMeta}
</td>
))}
<td className="vm-table-cell vm-table-cell_right">
{row.value}
</td>
</tr> </tr>
))} </thead>
</tbody> <tbody className="vm-table-body">
</table> {rows.map((row, index) => (
<tr
className="vm-table__row"
key={index}
>
{row.metadata.map((rowMeta, index2) => (
<td
className={classNames({
"vm-table-cell vm-table-cell_no-wrap": true,
"vm-table-cell_gray": rows[index - 1] && rows[index - 1].metadata[index2] === rowMeta
})}
key={index2}
>
{rowMeta}
</td>
))}
<td className="vm-table-cell vm-table-cell_right">
{row.value}
</td>
{hasCopyValue && (
<td className="vm-table-cell vm-table-cell_right">
{row.copyValue && (
<div className="vm-table-cell__content">
<Tooltip title="Copy row">
<Button
variant="text"
color="gray"
size="small"
startIcon={<CopyIcon/>}
onClick={createCopyHandler(row.copyValue)}
/>
</Tooltip>
</div>
)}
</td>
)}
</tr>
))}
</tbody>
</table>
</div>
); );
}; };

View file

@ -0,0 +1,11 @@
@use "src/styles/variables" as *;
.vm-table-view {
margin-top: -$padding-medium;
max-width: 100%;
overflow: auto;
table {
margin-top: 0;
}
}

View file

@ -1,6 +1,6 @@
export const MAX_QUERY_FIELDS = 4; export const MAX_QUERY_FIELDS = 4;
export const MAX_SERIES = { export const DEFAULT_MAX_SERIES = {
table: 100, table: 100,
chart: 20, chart: 20,
code: Infinity, code: 1000,
}; };

View file

@ -3,11 +3,10 @@ import { getQueryRangeUrl, getQueryUrl } from "../api/query-range";
import { useAppState } from "../state/common/StateContext"; import { useAppState } from "../state/common/StateContext";
import { InstantMetricResult, MetricBase, MetricResult } from "../api/types"; import { InstantMetricResult, MetricBase, MetricResult } from "../api/types";
import { isValidHttpUrl } from "../utils/url"; import { isValidHttpUrl } from "../utils/url";
import { ErrorTypes } from "../types"; import { ErrorTypes, SeriesLimits } from "../types";
import debounce from "lodash.debounce"; import debounce from "lodash.debounce";
import { DisplayType } from "../pages/CustomPanel/DisplayTypeSwitch"; import { DisplayType } from "../pages/CustomPanel/DisplayTypeSwitch";
import Trace from "../components/TraceQuery/Trace"; import Trace from "../components/TraceQuery/Trace";
import { MAX_SERIES } from "../constants/graph";
import { useQueryState } from "../state/query/QueryStateContext"; import { useQueryState } from "../state/query/QueryStateContext";
import { useTimeState } from "../state/time/TimeStateContext"; import { useTimeState } from "../state/time/TimeStateContext";
import { useCustomPanelState } from "../state/customPanel/CustomPanelStateContext"; import { useCustomPanelState } from "../state/customPanel/CustomPanelStateContext";
@ -17,9 +16,11 @@ interface FetchQueryParams {
visible: boolean visible: boolean
display?: DisplayType, display?: DisplayType,
customStep: number, customStep: number,
hideQuery?: number[]
showAllSeries?: boolean
} }
export const useFetchQuery = ({ predefinedQuery, visible, display, customStep }: FetchQueryParams): { interface FetchQueryReturn {
fetchUrl?: string[], fetchUrl?: string[],
isLoading: boolean, isLoading: boolean,
graphData?: MetricResult[], graphData?: MetricResult[],
@ -27,10 +28,28 @@ export const useFetchQuery = ({ predefinedQuery, visible, display, customStep }:
error?: ErrorTypes | string, error?: ErrorTypes | string,
warning?: string, warning?: string,
traces?: Trace[], traces?: Trace[],
} => { }
interface FetchDataParams {
fetchUrl: string[],
fetchQueue: AbortController[],
displayType: DisplayType,
query: string[],
stateSeriesLimits: SeriesLimits,
showAllSeries?: boolean,
}
export const useFetchQuery = ({
predefinedQuery,
visible,
display,
customStep,
hideQuery,
showAllSeries
}: FetchQueryParams): FetchQueryReturn => {
const { query } = useQueryState(); const { query } = useQueryState();
const { period } = useTimeState(); const { period } = useTimeState();
const { displayType, nocache, isTracingEnabled } = useCustomPanelState(); const { displayType, nocache, isTracingEnabled, seriesLimits: stateSeriesLimits } = useCustomPanelState();
const { serverUrl } = useAppState(); const { serverUrl } = useAppState();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@ -49,12 +68,19 @@ export const useFetchQuery = ({ predefinedQuery, visible, display, customStep }:
} }
}, [error]); }, [error]);
const fetchData = async (fetchUrl: string[], fetchQueue: AbortController[], displayType: DisplayType, query: string[]) => { const fetchData = async ({
fetchUrl,
fetchQueue,
displayType,
query,
stateSeriesLimits,
showAllSeries,
}: FetchDataParams) => {
const controller = new AbortController(); const controller = new AbortController();
setFetchQueue([...fetchQueue, controller]); setFetchQueue([...fetchQueue, controller]);
try { try {
const isDisplayChart = displayType === "chart"; const isDisplayChart = displayType === "chart";
const seriesLimit = MAX_SERIES[displayType]; const seriesLimit = showAllSeries ? Infinity : stateSeriesLimits[displayType];
const tempData: MetricBase[] = []; const tempData: MetricBase[] = [];
const tempTraces: Trace[] = []; const tempTraces: Trace[] = [];
let counter = 1; let counter = 1;
@ -100,6 +126,12 @@ export const useFetchQuery = ({ predefinedQuery, visible, display, customStep }:
const throttledFetchData = useCallback(debounce(fetchData, 800), []); const throttledFetchData = useCallback(debounce(fetchData, 800), []);
const filterExpr = (q: string, i: number) => {
const byQuery = q.trim();
const byHideQuery = hideQuery ? !hideQuery.includes(i) : true;
return byQuery && byHideQuery;
};
const fetchUrl = useMemo(() => { const fetchUrl = useMemo(() => {
const expr = predefinedQuery ?? query; const expr = predefinedQuery ?? query;
const displayChart = (display || displayType) === "chart"; const displayChart = (display || displayType) === "chart";
@ -111,21 +143,28 @@ export const useFetchQuery = ({ predefinedQuery, visible, display, customStep }:
} else if (isValidHttpUrl(serverUrl)) { } else if (isValidHttpUrl(serverUrl)) {
const updatedPeriod = { ...period }; const updatedPeriod = { ...period };
updatedPeriod.step = customStep; updatedPeriod.step = customStep;
return expr.filter(q => q.trim()).map(q => displayChart return expr.filter(filterExpr).map(q => displayChart
? getQueryRangeUrl(serverUrl, q, updatedPeriod, nocache, isTracingEnabled) ? getQueryRangeUrl(serverUrl, q, updatedPeriod, nocache, isTracingEnabled)
: getQueryUrl(serverUrl, q, updatedPeriod, isTracingEnabled)); : getQueryUrl(serverUrl, q, updatedPeriod, isTracingEnabled));
} else { } else {
setError(ErrorTypes.validServer); setError(ErrorTypes.validServer);
} }
}, },
[serverUrl, period, displayType, customStep]); [serverUrl, period, displayType, customStep, hideQuery]);
useEffect(() => { useEffect(() => {
if (!visible || !fetchUrl?.length) return; if (!visible || !fetchUrl?.length) return;
setIsLoading(true); setIsLoading(true);
const expr = predefinedQuery ?? query; const expr = predefinedQuery ?? query;
throttledFetchData(fetchUrl, fetchQueue, (display || displayType), expr); throttledFetchData({
}, [fetchUrl, visible]); fetchUrl,
fetchQueue,
displayType: display || displayType,
query: expr,
stateSeriesLimits,
showAllSeries,
});
}, [fetchUrl, visible, stateSeriesLimits, showAllSeries]);
useEffect(() => { useEffect(() => {
const fetchPast = fetchQueue.slice(0, -1); const fetchPast = fetchQueue.slice(0, -1);

View file

@ -2,13 +2,16 @@ import React, { FC, useEffect, useState, useRef, useMemo } from "preact/compat";
import { useSortedCategories } from "../../../../hooks/useSortedCategories"; import { useSortedCategories } from "../../../../hooks/useSortedCategories";
import { InstantMetricResult } from "../../../../api/types"; import { InstantMetricResult } from "../../../../api/types";
import Button from "../../../../components/Main/Button/Button"; import Button from "../../../../components/Main/Button/Button";
import { CloseIcon, SettingsIcon } from "../../../../components/Main/Icons"; import { CloseIcon, RestartIcon, SettingsIcon } from "../../../../components/Main/Icons";
import Popper from "../../../../components/Main/Popper/Popper"; import Popper from "../../../../components/Main/Popper/Popper";
import "./style.scss"; import "./style.scss";
import Checkbox from "../../../../components/Main/Checkbox/Checkbox"; import Checkbox from "../../../../components/Main/Checkbox/Checkbox";
import Tooltip from "../../../../components/Main/Tooltip/Tooltip"; import Tooltip from "../../../../components/Main/Tooltip/Tooltip";
import { useCustomPanelDispatch, useCustomPanelState } from "../../../../state/customPanel/CustomPanelStateContext";
import Switch from "../../../../components/Main/Switch/Switch";
import { arrayEquals } from "../../../../utils/array";
const title = "Display columns"; const title = "Table settings";
interface TableSettingsProps { interface TableSettingsProps {
data: InstantMetricResult[]; data: InstantMetricResult[];
@ -16,32 +19,33 @@ interface TableSettingsProps {
onChange: (arr: string[]) => void onChange: (arr: string[]) => void
} }
const TableSettings: FC<TableSettingsProps> = ({ data, defaultColumns, onChange }) => { const TableSettings: FC<TableSettingsProps> = ({ data, defaultColumns = [], onChange }) => {
const buttonRef = useRef<HTMLDivElement>(null);
const [openSettings, setOpenSettings] = useState(false); const { tableCompact } = useCustomPanelState();
const customPanelDispatch = useCustomPanelDispatch();
const columns = useSortedCategories(data); const columns = useSortedCategories(data);
const buttonRef = useRef<HTMLDivElement>(null);
const [openSettings, setOpenSettings] = useState(false);
const disabledButton = useMemo(() => !columns.length, [columns]); const disabledButton = useMemo(() => !columns.length, [columns]);
const [checkedColumns, setCheckedColumns] = useState(columns.map(col => col.key));
const handleChange = (key: string) => { const handleChange = (key: string) => {
setCheckedColumns(prev => checkedColumns.includes(key) ? prev.filter(col => col !== key) : [...prev, key]); onChange(defaultColumns.includes(key) ? defaultColumns.filter(col => col !== key) : [...defaultColumns, key]);
}; };
const handleClose = () => { const handleClose = () => {
setOpenSettings(false); setOpenSettings(false);
setCheckedColumns(defaultColumns || columns.map(col => col.key));
}; };
const handleReset = () => { const toggleTableCompact = () => {
setOpenSettings(false); customPanelDispatch({ type: "TOGGLE_TABLE_COMPACT" });
const value = columns.map(col => col.key);
setCheckedColumns(value);
onChange(value);
}; };
const handleApply = () => { const handleResetColumns = () => {
setOpenSettings(false); setOpenSettings(false);
onChange(checkedColumns); onChange(columns.map(col => col.key));
}; };
const createHandlerChange = (key: string) => () => { const createHandlerChange = (key: string) => () => {
@ -53,7 +57,9 @@ const TableSettings: FC<TableSettingsProps> = ({ data, defaultColumns, onChange
}; };
useEffect(() => { useEffect(() => {
setCheckedColumns(columns.map(col => col.key)); const values = columns.map(col => col.key);
if (arrayEquals(values, defaultColumns)) return;
onChange(values);
}, [columns]); }, [columns]);
return ( return (
@ -86,36 +92,39 @@ const TableSettings: FC<TableSettingsProps> = ({ data, defaultColumns, onChange
/> />
</div> </div>
<div className="vm-table-settings-popper-list"> <div className="vm-table-settings-popper-list">
<Switch
label={"Compact view"}
value={tableCompact}
onChange={toggleTableCompact}
/>
</div>
<div className="vm-table-settings-popper-list">
<div className="vm-table-settings-popper-list-header">
<h3 className="vm-table-settings-popper-list-header__title">Display columns</h3>
<Tooltip title="Reset to default">
<Button
color="primary"
variant="text"
size="small"
onClick={handleResetColumns}
startIcon={<RestartIcon/>}
/>
</Tooltip>
</div>
{columns.map(col => ( {columns.map(col => (
<div <div
className="vm-table-settings-popper-list__item" className="vm-table-settings-popper-list__item"
key={col.key} key={col.key}
> >
<Checkbox <Checkbox
checked={checkedColumns.includes(col.key)} checked={defaultColumns.includes(col.key)}
onChange={createHandlerChange(col.key)} onChange={createHandlerChange(col.key)}
label={col.key} label={col.key}
disabled={tableCompact}
/> />
</div> </div>
))} ))}
</div> </div>
<div className="vm-table-settings-popper__footer">
<Button
color="error"
variant="outlined"
size="small"
onClick={handleReset}
>
Reset
</Button>
<Button
variant="contained"
size="small"
onClick={handleApply}
>
apply
</Button>
</div>
</div> </div>
</Popper> </Popper>
</div> </div>

View file

@ -2,27 +2,31 @@
.vm-table-settings-popper { .vm-table-settings-popper {
display: grid; display: grid;
min-width: 250px;
&-list { &-list {
display: grid; display: grid;
gap: $padding-small; gap: $padding-small;
padding: $padding-global $padding-global $padding-medium; padding: $padding-global;
max-height: 350px; max-height: 350px;
overflow: auto; overflow: auto;
border-bottom: $border-divider;
&-header {
display: grid;
align-items: center;
justify-content: space-between;
grid-template-columns: 1fr auto;
min-height: 25px;
&__title {
font-weight: bold;
}
}
&__item { &__item {
font-size: $font-size; font-size: $font-size;
text-transform: capitalize; text-transform: capitalize;
} }
} }
&__footer {
min-width: 200px;
display: inline-grid;
grid-template-columns: 1fr 1fr;
gap: $padding-small;
align-items: center;
justify-content: center;
padding: 0 $padding-global $padding-global;
}
} }

View file

@ -6,24 +6,28 @@ import usePrevious from "../../../hooks/usePrevious";
import { MAX_QUERY_FIELDS } from "../../../constants/graph"; import { MAX_QUERY_FIELDS } from "../../../constants/graph";
import { useQueryDispatch, useQueryState } from "../../../state/query/QueryStateContext"; import { useQueryDispatch, useQueryState } from "../../../state/query/QueryStateContext";
import { useTimeDispatch } from "../../../state/time/TimeStateContext"; import { useTimeDispatch } from "../../../state/time/TimeStateContext";
import { DeleteIcon, PlayIcon, PlusIcon } from "../../../components/Main/Icons"; import { DeleteIcon, PlayIcon, PlusIcon, VisibilityIcon, VisibilityOffIcon } from "../../../components/Main/Icons";
import Button from "../../../components/Main/Button/Button"; import Button from "../../../components/Main/Button/Button";
import "./style.scss"; import "./style.scss";
import Tooltip from "../../../components/Main/Tooltip/Tooltip"; import Tooltip from "../../../components/Main/Tooltip/Tooltip";
import classNames from "classnames";
export interface QueryConfiguratorProps { export interface QueryConfiguratorProps {
error?: ErrorTypes | string; error?: ErrorTypes | string;
queryOptions: string[] queryOptions: string[]
onHideQuery: (queries: number[]) => void
} }
const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions }) => { const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions, onHideQuery }) => {
const { query, queryHistory, autocomplete } = useQueryState(); const { query, queryHistory, autocomplete } = useQueryState();
const queryDispatch = useQueryDispatch(); const queryDispatch = useQueryDispatch();
const timeDispatch = useTimeDispatch(); const timeDispatch = useTimeDispatch();
const [stateQuery, setStateQuery] = useState(query || []); const [stateQuery, setStateQuery] = useState(query || []);
const [hideQuery, setHideQuery] = useState<number[]>([]);
const prevStateQuery = usePrevious(stateQuery) as (undefined | string[]); const prevStateQuery = usePrevious(stateQuery) as (undefined | string[]);
const updateHistory = () => { const updateHistory = () => {
queryDispatch({ queryDispatch({
type: "SET_QUERY_HISTORY", payload: stateQuery.map((q, i) => { type: "SET_QUERY_HISTORY", payload: stateQuery.map((q, i) => {
@ -51,6 +55,10 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions })
setStateQuery(prev => prev.filter((q, i) => i !== index)); setStateQuery(prev => prev.filter((q, i) => i !== index));
}; };
const onToggleHideQuery = (index: number) => {
setHideQuery(prev => prev.includes(index) ? prev.filter(n => n !== index) : [...prev, index]);
};
const handleChangeQuery = (value: string, index: number) => { const handleChangeQuery = (value: string, index: number) => {
setStateQuery(prev => prev.map((q, i) => i === index ? value : q)); setStateQuery(prev => prev.map((q, i) => i === index ? value : q));
}; };
@ -76,6 +84,11 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions })
const createHandlerRemoveQuery = (i: number) => () => { const createHandlerRemoveQuery = (i: number) => () => {
onRemoveQuery(i); onRemoveQuery(i);
setHideQuery(prev => prev.map(n => n > i ? n - 1: n));
};
const createHandlerHideQuery = (i: number) => () => {
onToggleHideQuery(i);
}; };
useEffect(() => { useEffect(() => {
@ -84,11 +97,18 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions })
} }
}, [stateQuery]); }, [stateQuery]);
useEffect(() => {
onHideQuery(hideQuery);
}, [hideQuery]);
return <div className="vm-query-configurator vm-block"> return <div className="vm-query-configurator vm-block">
<div className="vm-query-configurator-list"> <div className="vm-query-configurator-list">
{stateQuery.map((q, i) => ( {stateQuery.map((q, i) => (
<div <div
className="vm-query-configurator-list-row" className={classNames({
"vm-query-configurator-list-row": true,
"vm-query-configurator-list-row_disabled": hideQuery.includes(i)
})}
key={i} key={i}
> >
<QueryEditor <QueryEditor
@ -101,8 +121,18 @@ const QueryConfigurator: FC<QueryConfiguratorProps> = ({ error, queryOptions })
onEnter={onRunQuery} onEnter={onRunQuery}
onChange={createHandlerChangeQuery(i)} onChange={createHandlerChangeQuery(i)}
label={`Query ${i + 1}`} label={`Query ${i + 1}`}
size={"small"} disabled={hideQuery.includes(i)}
/> />
<Tooltip title={hideQuery.includes(i) ? "Enable query" : "Disable query"}>
<div className="vm-query-configurator-list-row__button">
<Button
variant={"text"}
color={"gray"}
startIcon={hideQuery.includes(i) ? <VisibilityOffIcon/> : <VisibilityIcon/>}
onClick={createHandlerHideQuery(i)}
/>
</div>
</Tooltip>
{stateQuery.length > 1 && ( {stateQuery.length > 1 && (
<Tooltip title="Remove Query"> <Tooltip title="Remove Query">
<div className="vm-query-configurator-list-row__button"> <div className="vm-query-configurator-list-row__button">

View file

@ -9,10 +9,15 @@
&-row { &-row {
display: grid; display: grid;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto auto;
align-items: center; align-items: center;
gap: $padding-small; gap: $padding-small;
&_disabled {
filter: grayscale(100%);
opacity: 0.5;
}
&__button { &__button {
display: grid; display: grid;
width: 36px; width: 36px;

View file

@ -19,6 +19,7 @@ import { useSetQueryParams } from "./hooks/useSetQueryParams";
import "./style.scss"; import "./style.scss";
import Alert from "../../components/Main/Alert/Alert"; import Alert from "../../components/Main/Alert/Alert";
import TableView from "../../components/Views/TableView/TableView"; import TableView from "../../components/Views/TableView/TableView";
import Button from "../../components/Main/Button/Button";
const CustomPanel: FC = () => { const CustomPanel: FC = () => {
const { displayType, isTracingEnabled } = useCustomPanelState(); const { displayType, isTracingEnabled } = useCustomPanelState();
@ -29,10 +30,20 @@ const CustomPanel: FC = () => {
const [displayColumns, setDisplayColumns] = useState<string[]>(); const [displayColumns, setDisplayColumns] = useState<string[]>();
const [tracesState, setTracesState] = useState<Trace[]>([]); const [tracesState, setTracesState] = useState<Trace[]>([]);
const [hideQuery, setHideQuery] = useState<number[]>([]);
const [showAllSeries, setShowAllSeries] = useState(false);
const { customStep, yaxis } = useGraphState(); const { customStep, yaxis } = useGraphState();
const graphDispatch = useGraphDispatch(); const graphDispatch = useGraphDispatch();
const { queryOptions } = useFetchQueryOptions();
const { isLoading, liveData, graphData, error, warning, traces } = useFetchQuery({
visible: true,
customStep,
hideQuery,
showAllSeries
});
const setYaxisLimits = (limits: AxisRange) => { const setYaxisLimits = (limits: AxisRange) => {
graphDispatch({ type: "SET_YAXIS_LIMITS", payload: limits }); graphDispatch({ type: "SET_YAXIS_LIMITS", payload: limits });
}; };
@ -45,17 +56,19 @@ const CustomPanel: FC = () => {
timeDispatch({ type: "SET_PERIOD", payload: { from, to } }); timeDispatch({ type: "SET_PERIOD", payload: { from, to } });
}; };
const { queryOptions } = useFetchQueryOptions(); const handleShowAll = () => {
const { isLoading, liveData, graphData, error, warning, traces } = useFetchQuery({ setShowAllSeries(true);
visible: true, };
customStep
});
const handleTraceDelete = (trace: Trace) => { const handleTraceDelete = (trace: Trace) => {
const updatedTraces = tracesState.filter((data) => data.idValue !== trace.idValue); const updatedTraces = tracesState.filter((data) => data.idValue !== trace.idValue);
setTracesState([...updatedTraces]); setTracesState([...updatedTraces]);
}; };
const handleHideQuery = (queries: number[]) => {
setHideQuery(queries);
};
useEffect(() => { useEffect(() => {
if (traces) { if (traces) {
setTracesState([...tracesState, ...traces]); setTracesState([...tracesState, ...traces]);
@ -66,11 +79,16 @@ const CustomPanel: FC = () => {
setTracesState([]); setTracesState([]);
}, [displayType]); }, [displayType]);
useEffect(() => {
setShowAllSeries(false);
}, [query]);
return ( return (
<div className="vm-custom-panel"> <div className="vm-custom-panel">
<QueryConfigurator <QueryConfigurator
error={error} error={error}
queryOptions={queryOptions} queryOptions={queryOptions}
onHideQuery={handleHideQuery}
/> />
{isTracingEnabled && ( {isTracingEnabled && (
<div className="vm-custom-panel__trace"> <div className="vm-custom-panel__trace">
@ -80,22 +98,37 @@ const CustomPanel: FC = () => {
/> />
</div> </div>
)} )}
{isLoading && <Spinner />}
{error && <Alert variant="error">{error}</Alert>} {error && <Alert variant="error">{error}</Alert>}
{warning && <Alert variant="warning">{warning}</Alert>} {warning && <Alert variant="warning">
<div className="vm-custom-panel__warning">
<p>{warning}</p>
<Button
color="warning"
variant="outlined"
onClick={handleShowAll}
>
Show all
</Button>
</div>
</Alert>}
<div className="vm-custom-panel-body vm-block"> <div className="vm-custom-panel-body vm-block">
{isLoading && <Spinner />}
<div className="vm-custom-panel-body-header"> <div className="vm-custom-panel-body-header">
<DisplayTypeSwitch/> <DisplayTypeSwitch/>
{displayType === "chart" && <GraphSettings {displayType === "chart" && (
yaxis={yaxis} <GraphSettings
setYaxisLimits={setYaxisLimits} yaxis={yaxis}
toggleEnableLimits={toggleEnableLimits} setYaxisLimits={setYaxisLimits}
/>} toggleEnableLimits={toggleEnableLimits}
{displayType === "table" && <TableSettings />
data={liveData || []} )}
defaultColumns={displayColumns} {displayType === "table" && (
onChange={setDisplayColumns} <TableSettings
/>} data={liveData || []}
defaultColumns={displayColumns}
onChange={setDisplayColumns}
/>
)}
</div> </div>
{graphData && period && (displayType === "chart") && ( {graphData && period && (displayType === "chart") && (
<GraphView <GraphView
@ -108,7 +141,9 @@ const CustomPanel: FC = () => {
setPeriod={setPeriod} setPeriod={setPeriod}
/> />
)} )}
{liveData && (displayType === "code") && <JsonView data={liveData}/>} {liveData && (displayType === "code") && (
<JsonView data={liveData}/>
)}
{liveData && (displayType === "table") && ( {liveData && (displayType === "table") && (
<TableView <TableView
data={liveData} data={liveData}

View file

@ -2,10 +2,18 @@
.vm-custom-panel { .vm-custom-panel {
display: grid; display: grid;
grid-template-columns: 100%;
align-items: flex-start; align-items: flex-start;
gap: $padding-medium; gap: $padding-medium;
height: 100%; height: 100%;
&__warning {
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
justify-content: space-between;
}
&__trace { &__trace {
} }

View file

@ -0,0 +1,140 @@
import React, { FC, useState, useMemo } from "preact/compat";
import TextField from "../../../components/Main/TextField/TextField";
import "./style.scss";
import Button from "../../../components/Main/Button/Button";
import Trace from "../../../components/TraceQuery/Trace";
import { ErrorTypes } from "../../../types";
import classNames from "classnames";
import { useSnack } from "../../../contexts/Snackbar";
import { CopyIcon, RestartIcon } from "../../../components/Main/Icons";
interface JsonFormProps {
defaultJson?: string
defaultTile?: string
displayTitle?: boolean
editable?: boolean
resetValue?: string
onUpload: (json: string, title: string) => void
onClose: () => void
}
const JsonForm: FC<JsonFormProps> = ({
editable = false,
defaultTile = "JSON",
displayTitle = true,
defaultJson = "",
resetValue= "",
onClose,
onUpload,
}) => {
const { showInfoMessage } = useSnack();
const [json, setJson] = useState(defaultJson);
const [title, setTitle] = useState(defaultTile);
const [errorTitle, setErrorTitle] = useState("");
const [error, setError] = useState("");
const errorJson = useMemo(() => {
try {
const resp = JSON.parse(json);
const traceData = resp.trace || resp;
if (!traceData.duration_msec) return ErrorTypes.traceNotFound;
new Trace(traceData, "");
return "";
} catch (e) {
return e instanceof Error ? e.message : "Unknown error";
}
}, [json]);
const handleChangeTitle = (val: string) => {
setTitle(val);
};
const handleChangeJson = (val: string) => {
setError("");
setJson(val);
};
const handlerCopy = async () => {
await navigator.clipboard.writeText(json);
showInfoMessage({ text: "Formatted JSON has been copied", type: "success" });
};
const handleReset = () => {
setJson(resetValue);
};
const handleApply = () => {
setError(errorJson);
const titleTrim = title.trim();
if (!titleTrim) setErrorTitle(ErrorTypes.emptyTitle);
if (errorJson || errorTitle) return;
onUpload(json, title);
onClose();
};
return (
<div
className={classNames({
"vm-json-form": true,
"vm-json-form_one-field": !displayTitle
})}
>
{displayTitle && (
<TextField
value={title}
label="Title"
error={errorTitle}
onEnter={handleApply}
onChange={handleChangeTitle}
/>
)}
<TextField
value={json}
label="JSON"
type="textarea"
error={error}
autofocus
onChange={handleChangeJson}
disabled={!editable}
/>
<div className="vm-json-form-footer">
<div className="vm-json-form-footer__controls">
<Button
variant="outlined"
startIcon={<CopyIcon/>}
onClick={handlerCopy}
>
Copy JSON
</Button>
{resetValue && (
<Button
variant="text"
startIcon={<RestartIcon/>}
onClick={handleReset}
>
Reset JSON
</Button>
)}
</div>
<div className="vm-json-form-footer__controls vm-json-form-footer__controls_right">
<Button
variant="outlined"
color="error"
onClick={onClose}
>
Cancel
</Button>
<Button
variant="contained"
onClick={handleApply}
>
apply
</Button>
</div>
</div>
</div>
);
};
export default JsonForm;

View file

@ -0,0 +1,41 @@
@use "src/styles/variables" as *;
.vm-json-form {
display: grid;
grid-template-rows: auto calc(90vh - 78px - ($padding-medium*3)) auto;
gap: $padding-global;
width: 70vw;
max-width: 1000px;
max-height: 900px;
&_one-field {
grid-template-rows: calc(90vh - 78px - ($padding-medium*3)) auto;
}
textarea {
overflow: auto;
width: 100%;
height: 100%;
}
&-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: $padding-small;
&__controls {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: flex-start;
gap: $padding-small;
&_right {
display: grid;
grid-template-columns: repeat(2, 90px);
justify-content: flex-end;
}
}
}
}

View file

@ -0,0 +1,177 @@
import React, { FC, useMemo, useState } from "preact/compat";
import { ChangeEvent } from "react";
import Trace from "../../components/TraceQuery/Trace";
import TracingsView from "../../components/TraceQuery/TracingsView";
import Tooltip from "../../components/Main/Tooltip/Tooltip";
import Button from "../../components/Main/Button/Button";
import Alert from "../../components/Main/Alert/Alert";
import "./style.scss";
import { CloseIcon } from "../../components/Main/Icons";
import Modal from "../../components/Main/Modal/Modal";
import JsonForm from "./JsonForm/JsonForm";
import { ErrorTypes } from "../../types";
const TracePage: FC = () => {
const [openModal, setOpenModal] = useState(false);
const [tracesState, setTracesState] = useState<Trace[]>([]);
const [errors, setErrors] = useState<{filename: string, text: string}[]>([]);
const hasTraces = useMemo(() => !!tracesState.length, [tracesState]);
const handleOpenModal = () => {
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
};
const handleError = (e: Error, filename = "") => {
setErrors(prev => [{ filename, text: `: ${e.message}` }, ...prev]);
};
const handleOnload = (result: string, filename: string) => {
try {
const resp = JSON.parse(result);
const traceData = resp.trace || resp;
if (!traceData.duration_msec) {
handleError(new Error(ErrorTypes.traceNotFound), filename);
return;
}
const trace = new Trace(traceData, filename);
setTracesState(prev => [trace, ...prev]);
} catch (e) {
if (e instanceof Error) handleError(e, filename);
}
};
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setErrors([]);
const files = Array.from(e.target.files || []);
files.map(f => {
const reader = new FileReader();
const filename = f?.name || "";
reader.onload = (e) => {
const result = String(e.target?.result);
handleOnload(result, filename);
};
reader.readAsText(f);
});
e.target.value = "";
};
const handleTraceDelete = (trace: Trace) => {
const updatedTraces = tracesState.filter((data) => data.idValue !== trace.idValue);
setTracesState([...updatedTraces]);
};
const handleCloseError = (index: number) => {
setErrors(prev => prev.filter((e,i) => i !== index));
};
const createHandlerCloseError = (index: number) => () => {
handleCloseError(index);
};
const UploadButtons = () => (
<div className="vm-trace-page-controls">
<Button
variant="outlined"
onClick={handleOpenModal}
>
Paste JSON
</Button>
<Tooltip title="The file must contain tracing information in JSON format">
<Button>
Upload Files
<input
id="json"
type="file"
accept="application/json"
multiple
title=" "
onChange={handleChange}
/>
</Button>
</Tooltip>
</div>
);
return (
<div className="vm-trace-page">
<div className="vm-trace-page-header">
<div className="vm-trace-page-header-errors">
{errors.map((error, i) => (
<div
className="vm-trace-page-header-errors-item"
key={`${error}_${i}`}
>
<Alert variant="error">
<b className="vm-trace-page-header-errors-item__filename">{error.filename}</b>
<span>{error.text}</span>
</Alert>
<Button
className="vm-trace-page-header-errors-item__close"
startIcon={<CloseIcon/>}
variant="text"
color="error"
onClick={createHandlerCloseError(i)}
/>
</div>
))}
</div>
<div>
{hasTraces && <UploadButtons/>}
</div>
</div>
{hasTraces && (
<div>
<TracingsView
jsonEditor={true}
traces={tracesState}
onDeleteClick={handleTraceDelete}
/>
</div>
)}
{!hasTraces && (
<div className="vm-trace-page-preview">
<p className="vm-trace-page-preview__text">
Please, upload file with JSON response content.
{"\n"}
The file must contain tracing information in JSON format.
{"\n"}
In order to use tracing please refer to the doc:&nbsp;
<a
href="https://docs.victoriametrics.com/#query-tracing"
target="_blank"
rel="noreferrer"
>
https://docs.victoriametrics.com/#query-tracing
</a>
{"\n"}
Tracing graph will be displayed after file upload.
</p>
<UploadButtons/>
</div>
)}
{openModal && (
<Modal
title="Paste JSON"
onClose={handleCloseModal}
>
<JsonForm
editable
displayTitle
defaultTile={`JSON ${tracesState.length + 1}`}
onClose={handleCloseModal}
onUpload={handleOnload}
/>
</Modal>
)}
</div>
);
};
export default TracePage;

View file

@ -0,0 +1,66 @@
@use "src/styles/variables" as *;
.vm-trace-page {
display: flex;
flex-direction: column;
padding: $padding-global;
min-height: 100%;
&-controls {
display: grid;
grid-template-columns: 1fr 1fr;
gap: $padding-global;
align-items: center;
justify-content: center;
}
&-header {
display: grid;
grid-template-columns: 1fr auto;
align-items: start;
gap: $padding-global;
margin-bottom: $padding-medium;
&-errors {
display: grid;
align-items: flex-start;
justify-content: stretch;
grid-template-columns: 1fr;
gap: $padding-medium;
&-item {
position: relative;
display: grid;
align-items: center;
justify-content: stretch;
&__filename {
min-height: 20px;
}
&__close {
position: absolute;
top: auto;
right: $padding-small;
z-index: 2;
}
}
}
}
&-preview {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&__text {
margin-bottom: $padding-small;
font-size: $font-size-medium;
white-space: pre-line;
text-align: center;
line-height: 1.8;
}
}
}

View file

@ -3,6 +3,7 @@ const router = {
dashboards: "/dashboards", dashboards: "/dashboards",
cardinality: "/cardinality", cardinality: "/cardinality",
topQueries: "/top-queries", topQueries: "/top-queries",
trace: "/trace"
}; };
export interface RouterOptions { export interface RouterOptions {
@ -18,7 +19,6 @@ const routerOptionsDefault = {
header: { header: {
timeSelector: true, timeSelector: true,
executionControls: true, executionControls: true,
globalSettings: true,
} }
}; };
@ -28,7 +28,6 @@ export const routerOptions: {[key: string]: RouterOptions} = {
[router.cardinality]: { [router.cardinality]: {
header: { header: {
cardinalityDatePicker: true, cardinalityDatePicker: true,
globalSettings: true,
} }
} }
}; };

View file

@ -1,25 +1,34 @@
import { DisplayType, displayTypeTabs } from "../../pages/CustomPanel/DisplayTypeSwitch"; import { DisplayType, displayTypeTabs } from "../../pages/CustomPanel/DisplayTypeSwitch";
import { getFromStorage, saveToStorage } from "../../utils/storage";
import { getQueryStringValue } from "../../utils/query-string"; import { getQueryStringValue } from "../../utils/query-string";
import { getFromStorage, saveToStorage } from "../../utils/storage";
import { SeriesLimits } from "../../types";
import { DEFAULT_MAX_SERIES } from "../../constants/graph";
export interface CustomPanelState { export interface CustomPanelState {
displayType: DisplayType; displayType: DisplayType;
nocache: boolean; nocache: boolean;
isTracingEnabled: boolean; isTracingEnabled: boolean;
seriesLimits: SeriesLimits
tableCompact: boolean;
} }
export type CustomPanelAction = export type CustomPanelAction =
| { type: "SET_DISPLAY_TYPE", payload: DisplayType } | { type: "SET_DISPLAY_TYPE", payload: DisplayType }
| { type: "SET_SERIES_LIMITS", payload: SeriesLimits }
| { type: "TOGGLE_NO_CACHE"} | { type: "TOGGLE_NO_CACHE"}
| { type: "TOGGLE_QUERY_TRACING" } | { type: "TOGGLE_QUERY_TRACING" }
| { type: "TOGGLE_TABLE_COMPACT" }
const queryTab = getQueryStringValue("g0.tab", 0) as string; const queryTab = getQueryStringValue("g0.tab", 0) as string;
const displayType = displayTypeTabs.find(t => t.prometheusCode === +queryTab || t.value === queryTab); const displayType = displayTypeTabs.find(t => t.prometheusCode === +queryTab || t.value === queryTab);
const limitsStorage = getFromStorage("SERIES_LIMITS") as string;
export const initialCustomPanelState: CustomPanelState = { export const initialCustomPanelState: CustomPanelState = {
displayType: (displayType?.value || "chart") as DisplayType, displayType: (displayType?.value || "chart") as DisplayType,
nocache: getFromStorage("NO_CACHE") as boolean || false, nocache: false,
isTracingEnabled: getFromStorage("QUERY_TRACING") as boolean || false, isTracingEnabled: false,
seriesLimits: limitsStorage ? JSON.parse(getFromStorage("SERIES_LIMITS") as string) : DEFAULT_MAX_SERIES,
tableCompact: getFromStorage("TABLE_COMPACT") as boolean || false,
}; };
export function reducer(state: CustomPanelState, action: CustomPanelAction): CustomPanelState { export function reducer(state: CustomPanelState, action: CustomPanelAction): CustomPanelState {
@ -29,19 +38,29 @@ export function reducer(state: CustomPanelState, action: CustomPanelAction): Cus
...state, ...state,
displayType: action.payload displayType: action.payload
}; };
case "SET_SERIES_LIMITS":
saveToStorage("SERIES_LIMITS", JSON.stringify(action.payload));
return {
...state,
seriesLimits: action.payload
};
case "TOGGLE_QUERY_TRACING": case "TOGGLE_QUERY_TRACING":
saveToStorage("QUERY_TRACING", !state.isTracingEnabled);
return { return {
...state, ...state,
isTracingEnabled: !state.isTracingEnabled, isTracingEnabled: !state.isTracingEnabled,
}; };
case "TOGGLE_NO_CACHE": case "TOGGLE_NO_CACHE":
saveToStorage("NO_CACHE", !state.nocache);
return { return {
...state, ...state,
nocache: !state.nocache nocache: !state.nocache
}; };
case "TOGGLE_TABLE_COMPACT":
saveToStorage("TABLE_COMPACT", !state.tableCompact);
return {
...state,
tableCompact: !state.tableCompact
};
default: default:
throw new Error(); throw new Error();
} }

View file

@ -28,6 +28,11 @@ b {
font-weight: bold; font-weight: bold;
} }
textarea,
input {
cursor: text;
}
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button { input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none; -webkit-appearance: none;
@ -38,5 +43,5 @@ input[type=number]::-webkit-outer-spin-button {
position: fixed; position: fixed;
left: $padding-global; left: $padding-global;
bottom: $padding-global; bottom: $padding-global;
z-index: 9; z-index: 999;
} }

View file

@ -18,6 +18,7 @@ $color-text-secondary: rgba($color-text, 0.6);
$color-text-disabled: rgba($color-text, 0.4); $color-text-disabled: rgba($color-text, 0.4);
$color-black: #110f0f; $color-black: #110f0f;
$color-dove-gray: #616161;
$color-silver: #C4C4C4; $color-silver: #C4C4C4;
$color-alto: #D8D8D8; $color-alto: #D8D8D8;
$color-white: #ffffff; $color-white: #ffffff;
@ -30,7 +31,7 @@ $color-tropical-blue: #C9E3F6;
$color-background-body: var(--color-background-body); $color-background-body: var(--color-background-body);
$color-background-block: var(--color-background-block); $color-background-block: var(--color-background-block);
$color-background-modal: rgba($color-black, 0.7); $color-background-modal: rgba($color-black, 0.7);
$color-background-tooltip: rgba(97, 97, 97, 0.92); $color-background-tooltip: rgba($color-dove-gray, 0.92);
/************* padding *************/ /************* padding *************/

View file

@ -35,12 +35,16 @@ export interface DataSeries extends MetricBase{
export interface InstantDataSeries { export interface InstantDataSeries {
metadata: string[]; // just ordered columns metadata: string[]; // just ordered columns
value: string; value: string;
copyValue: string;
} }
export enum ErrorTypes { export enum ErrorTypes {
emptyServer = "Please enter Server URL", emptyServer = "Please enter Server URL",
validServer = "Please provide a valid Server URL", validServer = "Please provide a valid Server URL",
validQuery = "Please enter a valid Query and execute it" validQuery = "Please enter a valid Query and execute it",
traceNotFound = "Not found the tracing information",
emptyTitle = "Please enter title",
positiveNumber = "Please enter positive number"
} }
export interface PanelSettings { export interface PanelSettings {
@ -95,3 +99,9 @@ export interface TopQueriesData extends TopQueryStats{
topByCount: TopQuery[] topByCount: TopQuery[]
topBySumDuration: TopQuery[] topBySumDuration: TopQuery[]
} }
export interface SeriesLimits {
table: number,
chart: number,
code: number,
}

View file

@ -1,6 +1,6 @@
import { MetricBase } from "../api/types"; import { MetricBase } from "../api/types";
export const getNameForMetric = (result: MetricBase, alias?: string): string => { export const getNameForMetric = (result: MetricBase, alias?: string, connector = ": ", quoteValue = false): string => {
const { __name__, ...freeFormFields } = result.metric; const { __name__, ...freeFormFields } = result.metric;
const name = alias || __name__ || ""; const name = alias || __name__ || "";
@ -8,5 +8,7 @@ export const getNameForMetric = (result: MetricBase, alias?: string): string =>
return name || `Result ${result.group}`; // a bit better than just {} for case of aggregation functions return name || `Result ${result.group}`; // a bit better than just {} for case of aggregation functions
} }
return `${name} {${Object.entries(freeFormFields).map(e => `${e[0]}: ${e[1]}`).join(", ")}}`; return `${name} {${Object.entries(freeFormFields).map(e =>
`${e[0]}${connector}${(quoteValue ? `"${e[1]}"` : e[1])}`
).join(", ")}}`;
}; };

View file

@ -4,6 +4,8 @@ export type StorageKeys = "BASIC_AUTH_DATA"
| "AUTOCOMPLETE" | "AUTOCOMPLETE"
| "NO_CACHE" | "NO_CACHE"
| "QUERY_TRACING" | "QUERY_TRACING"
| "SERIES_LIMITS"
| "TABLE_COMPACT"
export const saveToStorage = (key: StorageKeys, value: string | boolean | Record<string, unknown>): void => { export const saveToStorage = (key: StorageKeys, value: string | boolean | Record<string, unknown>): void => {
if (value) { if (value) {

View file

@ -1,36 +0,0 @@
import dayjs from "dayjs";
import { SetupTooltip } from "./types";
import { getColorLine, formatPrettyNumber, getLegendLabel } from "./helpers";
import { DATE_FULL_TIMEZONE_FORMAT } from "../../constants/date";
// TODO create jsx component
export const setTooltip = ({ u, tooltipIdx, metrics, series, tooltip, tooltipOffset, unit = "" }: SetupTooltip): void => {
const { seriesIdx, dataIdx } = tooltipIdx;
if (seriesIdx === null || dataIdx === undefined) return;
const dataSeries = u.data[seriesIdx][dataIdx];
const dataTime = u.data[0][dataIdx];
const metric = metrics[seriesIdx - 1]?.metric || {};
const selectedSeries = series[seriesIdx];
const color = getColorLine(selectedSeries.label || "");
const { width, height } = u.over.getBoundingClientRect();
const top = u.valToPos((dataSeries || 0), series[seriesIdx]?.scale || "1");
const lft = u.valToPos(dataTime, "x");
const { width: tooltipWidth, height: tooltipHeight } = tooltip.getBoundingClientRect();
const overflowX = lft + tooltipWidth >= width;
const overflowY = top + tooltipHeight >= height;
tooltip.style.display = "grid";
tooltip.style.top = `${tooltipOffset.top + top + 10 - (overflowY ? tooltipHeight + 10 : 0)}px`;
tooltip.style.left = `${tooltipOffset.left + lft + 10 - (overflowX ? tooltipWidth + 20 : 0)}px`;
const metricName = (selectedSeries.label || "").replace(/{.+}/gmi, "").trim();
const name = getLegendLabel(metricName);
const date = dayjs(new Date(dataTime * 1000)).format(DATE_FULL_TIMEZONE_FORMAT);
const info = Object.keys(metric).filter(k => k !== "__name__").map(k => `<div><b>${k}</b>: ${metric[k]}</div>`).join("");
const marker = `<div class="u-tooltip__marker" style="background: ${color}"></div>`;
tooltip.innerHTML = `<div>${date}</div>
<div class="u-tooltip-data">
${marker}${name}: <b class="u-tooltip-data__value">${formatPrettyNumber(dataSeries)}</b> ${unit}
</div>
<div class="u-tooltip__info">${info}</div>`;
};

View file

@ -1,21 +1,4 @@
import uPlot, { Series } from "uplot"; import uPlot, { Series } from "uplot";
import { MetricResult } from "../../api/types";
export interface SetupTooltip {
u: uPlot,
metrics: MetricResult[],
series: Series[],
tooltip: HTMLDivElement,
unit?: string,
tooltipOffset: {
left: number,
top: number
},
tooltipIdx: {
seriesIdx: number | null,
dataIdx: number | undefined
}
}
export interface HideSeriesArgs { export interface HideSeriesArgs {
hideSeries: string[], hideSeries: string[],

View file

@ -1,14 +1,5 @@
{ {
"__inputs": [ "__inputs": [],
{
"name": "DS_VICTORIAMETRICS",
"label": "VictoriaMetrics",
"description": "",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__elements": [], "__elements": [],
"__requires": [ "__requires": [
{ {
@ -116,7 +107,7 @@
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "${DS_VICTORIAMETRICS}" "uid": "${ds}"
}, },
"expr": "sum(increase(vm_tenant_inserted_rows_total{job=~\"$job\", instance=~\"$instance\",accountID=~\"$account\", projectID=~\"$project\"}[1m])/60) by (accountID,projectID) ", "expr": "sum(increase(vm_tenant_inserted_rows_total{job=~\"$job\", instance=~\"$instance\",accountID=~\"$account\", projectID=~\"$project\"}[1m])/60) by (accountID,projectID) ",
"interval": "", "interval": "",
@ -214,7 +205,7 @@
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "${DS_VICTORIAMETRICS}" "uid": "${ds}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "sum(rate(vm_tenant_select_requests_total{job=~\"$job\", instance=~\"$instance.*\",accountID=~\"$account\", projectID=~\"$project\"}[$__rate_interval])) by (accountID,projectID) ", "expr": "sum(rate(vm_tenant_select_requests_total{job=~\"$job\", instance=~\"$instance.*\",accountID=~\"$account\", projectID=~\"$project\"}[$__rate_interval])) by (accountID,projectID) ",
@ -320,7 +311,7 @@
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "${DS_VICTORIAMETRICS}" "uid": "${ds}"
}, },
"expr": "sum(vm_tenant_active_timeseries{job=~\"$job\", instance=~\"$instance.*\",accountID=~\"$account\",projectID=~\"$project\"}) by(accountID,projectID)", "expr": "sum(vm_tenant_active_timeseries{job=~\"$job\", instance=~\"$instance.*\",accountID=~\"$account\",projectID=~\"$project\"}) by(accountID,projectID)",
"format": "time_series", "format": "time_series",
@ -418,7 +409,7 @@
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "${DS_VICTORIAMETRICS}" "uid": "${ds}"
}, },
"expr": "sum(increase(vm_tenant_timeseries_created_total{job=~\"$job\", instance=~\"$instance\",accountID=~\"$account\", projectID=~\"$project\"}[1m])/60) by(accountID,projectID)", "expr": "sum(increase(vm_tenant_timeseries_created_total{job=~\"$job\", instance=~\"$instance\",accountID=~\"$account\", projectID=~\"$project\"}[1m])/60) by(accountID,projectID)",
"interval": "", "interval": "",
@ -513,7 +504,7 @@
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "${DS_VICTORIAMETRICS}" "uid": "${ds}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "sum(vm_tenant_used_tenant_bytes{job=~\"$job\", instance=~\"$instance\",accountID=~\"$account\",projectID=~\"$project\"}) by(accountID,projectID)", "expr": "sum(vm_tenant_used_tenant_bytes{job=~\"$job\", instance=~\"$instance\",accountID=~\"$account\",projectID=~\"$project\"}) by(accountID,projectID)",

View file

@ -4,8 +4,8 @@
{ {
"builtIn": 1, "builtIn": 1,
"datasource": { "datasource": {
"type": "grafana", "type": "datasource",
"uid": "-- Grafana --" "uid": "grafana"
}, },
"enable": true, "enable": true,
"hide": true, "hide": true,

File diff suppressed because it is too large Load diff

View file

@ -1713,7 +1713,6 @@
"collapsed": true, "collapsed": true,
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "P4169E866C3094E38"
}, },
"gridPos": { "gridPos": {
"h": 1, "h": 1,
@ -2031,7 +2030,6 @@
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
"uid": "P4169E866C3094E38"
}, },
"refId": "A" "refId": "A"
} }

View file

@ -2,8 +2,8 @@
DOCKER_NAMESPACE := victoriametrics DOCKER_NAMESPACE := victoriametrics
ROOT_IMAGE ?= alpine:3.16.2 ROOT_IMAGE ?= alpine:3.17.0
CERTS_IMAGE := alpine:3.16.2 CERTS_IMAGE := alpine:3.17.0
GO_BUILDER_IMAGE := golang:1.19.3-alpine GO_BUILDER_IMAGE := golang:1.19.3-alpine
BUILDER_IMAGE := local/builder:2.0.0-$(shell echo $(GO_BUILDER_IMAGE) | tr :/ __)-1 BUILDER_IMAGE := local/builder:2.0.0-$(shell echo $(GO_BUILDER_IMAGE) | tr :/ __)-1
BASE_IMAGE := local/base:1.1.3-$(shell echo $(ROOT_IMAGE) | tr :/ __)-$(shell echo $(CERTS_IMAGE) | tr :/ __) BASE_IMAGE := local/base:1.1.3-$(shell echo $(ROOT_IMAGE) | tr :/ __)-$(shell echo $(CERTS_IMAGE) | tr :/ __)

View file

@ -54,6 +54,7 @@ groups:
for: 15m for: 15m
labels: labels:
severity: warning severity: warning
show_at: dashboard
annotations: annotations:
dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=52&var-instance={{ $labels.instance }}" dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=52&var-instance={{ $labels.instance }}"
summary: "Too many errors served for {{ $labels.job }} path {{ $labels.path }} (instance {{ $labels.instance }})" summary: "Too many errors served for {{ $labels.job }} path {{ $labels.path }} (instance {{ $labels.instance }})"
@ -72,6 +73,7 @@ groups:
for: 15m for: 15m
labels: labels:
severity: warning severity: warning
show_at: dashboard
annotations: annotations:
dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=44&var-instance={{ $labels.instance }}" dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=44&var-instance={{ $labels.instance }}"
summary: "Too many RPC errors for {{ $labels.job }} (instance {{ $labels.instance }})" summary: "Too many RPC errors for {{ $labels.job }} (instance {{ $labels.instance }})"
@ -83,6 +85,7 @@ groups:
for: 15m for: 15m
labels: labels:
severity: warning severity: warning
show_at: dashboard
annotations: annotations:
dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=133&var-instance={{ $labels.instance }}" dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=133&var-instance={{ $labels.instance }}"
summary: "vmstorage on instance {{ $labels.instance }} is constantly hitting concurrent flushes limit" summary: "vmstorage on instance {{ $labels.instance }} is constantly hitting concurrent flushes limit"
@ -179,6 +182,7 @@ groups:
for: 15m for: 15m
labels: labels:
severity: warning severity: warning
show_at: dashboard
annotations: annotations:
dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=139&var-instance={{ $labels.instance }}" dashboard: "http://localhost:3000/d/oS7Bi_0Wz?viewPanel=139&var-instance={{ $labels.instance }}"
summary: "Connection between vminsert on {{ $labels.instance }} and vmstorage on {{ $labels.addr }} is saturated" summary: "Connection between vminsert on {{ $labels.instance }} and vmstorage on {{ $labels.addr }} is saturated"
@ -186,3 +190,4 @@ groups:
is saturated by more than 90% and vminsert won't be able to keep up.\n is saturated by more than 90% and vminsert won't be able to keep up.\n
This usually means that more vminsert or vmstorage nodes must be added to the cluster in order to increase This usually means that more vminsert or vmstorage nodes must be added to the cluster in order to increase
the total number of vminsert -> vmstorage links." the total number of vminsert -> vmstorage links."

View file

@ -120,3 +120,15 @@ groups:
summary: "Instance {{ $labels.instance }} reached 90% of the limit" summary: "Instance {{ $labels.instance }} reached 90% of the limit"
description: "Max series limit set via -remoteWrite.maxDailySeries flag is close to reaching the max value. description: "Max series limit set via -remoteWrite.maxDailySeries flag is close to reaching the max value.
Then samples for new time series will be dropped instead of sending them to remote storage systems." Then samples for new time series will be dropped instead of sending them to remote storage systems."
- alert: ConfigurationReloadFailure
expr: |
vm_promscrape_config_last_reload_successful != 1
or
vmagent_relabel_config_last_reload_successful != 1
labels:
severity: warning
annotations:
summary: "Configuration reload failed for vmagent instance {{ $labels.instance }}"
description: "Configuration hot-reload failed for vmagent on instance {{ $labels.instance }}.
Check vmagent's logs for detailed error message."

View file

@ -0,0 +1,72 @@
# File contains default list of alerts for мьфдуке service.
# The alerts below are just recommendations and may require some updates
# and threshold calibration according to every specific setup.
groups:
# Alerts group for vmalert assumes that Grafana dashboard
# https://grafana.com/grafana/dashboards/14950-victoriametrics-vmalert is installed.
# Pls update the `dashboard` annotation according to your setup.
- name: vmalert
interval: 30s
rules:
- alert: ConfigurationReloadFailure
expr: vmalert_config_last_reload_successful != 1
labels:
severity: warning
annotations:
summary: "Configuration reload failed for vmalert instance {{ $labels.instance }}"
description: "Configuration hot-reload failed for vmalert on instance {{ $labels.instance }}.
Check vmalert's logs for detailed error message."
- alert: AlertingRulesError
expr: sum(vmalert_alerting_rules_error) by(job, instance, group) > 0
for: 5m
labels:
severity: warning
annotations:
dashboard: "http://localhost:3000/d/LzldHAVnz?viewPanel=13&var-instance={{ $labels.instance }}&var-group={{ $labels.group }}"
summary: "Alerting rules are failing for vmalert instance {{ $labels.instance }}"
description: "Alerting rules execution is failing for group \"{{ $labels.group }}\".
Check vmalert's logs for detailed error message."
- alert: RecordingRulesError
expr: sum(vmalert_recording_rules_error) by(job, instance, group) > 0
for: 5m
labels:
severity: warning
annotations:
dashboard: "http://localhost:3000/d/LzldHAVnz?viewPanel=30&var-instance={{ $labels.instance }}&var-group={{ $labels.group }}"
summary: "Recording rules are failing for vmalert instance {{ $labels.instance }}"
description: "Recording rules execution is failing for group \"{{ $labels.group }}\".
Check vmalert's logs for detailed error message."
- alert: RecordingRulesNoData
expr: sum(vmalert_recording_rules_last_evaluation_samples) by(job, group, recording) < 1
for: 30m
labels:
severity: warning
annotations:
dashboard: "http://localhost:3000/d/LzldHAVnz?viewPanel=33&var-group={{ $labels.group }}"
summary: "Recording rule {{ $labels.recording }} ({ $labels.group }}) produces no data"
description: "Recording rule \"{{ $labels.recording }}\" from group \"{{ $labels.group }}\"
produces 0 samples over the last 30min. It might be caused by a misconfiguration
or incorrect query expression."
- alert: RemoteWriteErrors
expr: sum(increase(vmalert_remotewrite_errors_total[5m])) by(job, instance) > 0
for: 15m
labels:
severity: warning
annotations:
summary: "vmalert instance {{ $labels.instance }} is failing to push metrics to remote write URL"
description: "vmalert instance {{ $labels.instance }} is failing to push metrics generated via alerting
or recording rules to the configured remote write URL. Check vmalert's logs for detailed error message."
- alert: AlertmanagerErrors
expr: sum(increase(vmalert_alerts_send_errors_total[5m])) by(job, instance, addr) > 0
for: 15m
labels:
severity: warning
annotations:
summary: "vmalert instance {{ $labels.instance }} is failing to send notifications to Alertmanager"
description: "vmalert instance {{ $labels.instance }} is failing to send alert notifications to \"{{ $labels.addr }}\".
Check vmalert's logs for detailed error message."

View file

@ -91,6 +91,7 @@ services:
- ./alerts-cluster.yml:/etc/alerts/alerts.yml - ./alerts-cluster.yml:/etc/alerts/alerts.yml
- ./alerts-health.yml:/etc/alerts/alerts-health.yml - ./alerts-health.yml:/etc/alerts/alerts-health.yml
- ./alerts-vmagent.yml:/etc/alerts/alerts-vmagent.yml - ./alerts-vmagent.yml:/etc/alerts/alerts-vmagent.yml
- ./alerts-vmalert.yml:/etc/alerts/alerts-vmalert.yml
command: command:
- '--datasource.url=http://vmselect:8481/select/0/prometheus' - '--datasource.url=http://vmselect:8481/select/0/prometheus'
- '--remoteRead.url=http://vmselect:8481/select/0/prometheus' - '--remoteRead.url=http://vmselect:8481/select/0/prometheus'

View file

@ -66,6 +66,7 @@ services:
- ./alerts.yml:/etc/alerts/alerts.yml - ./alerts.yml:/etc/alerts/alerts.yml
- ./alerts-health.yml:/etc/alerts/alerts-health.yml - ./alerts-health.yml:/etc/alerts/alerts-health.yml
- ./alerts-vmagent.yml:/etc/alerts/alerts-vmagent.yml - ./alerts-vmagent.yml:/etc/alerts/alerts-vmagent.yml
- ./alerts-vmalert.yml:/etc/alerts/alerts-vmalert.yml
command: command:
- "--datasource.url=http://victoriametrics:8428/" - "--datasource.url=http://victoriametrics:8428/"
- "--remoteRead.url=http://victoriametrics:8428/" - "--remoteRead.url=http://victoriametrics:8428/"

View file

@ -108,6 +108,8 @@ See also [case studies](https://docs.victoriametrics.com/CaseStudies.html).
### Other articles ### Other articles
* [How ClickHouse inspired us to build a high performance time series database](https://www.youtube.com/watch?v=p9qjb_yoBro). See also [slides](https://docs.google.com/presentation/d/1SdFrwsyR-HMXfbzrY8xfDZH_Dg6E7E5NJ84tQozMn3w/edit?usp=sharing). * [How ClickHouse inspired us to build a high performance time series database](https://www.youtube.com/watch?v=p9qjb_yoBro). See also [slides](https://docs.google.com/presentation/d/1SdFrwsyR-HMXfbzrY8xfDZH_Dg6E7E5NJ84tQozMn3w/edit?usp=sharing)
* [OSA Con 2022: Specifics of data analysis in Time Series Databases](https://www.youtube.com/watch?v=_zORxrgLtec)
* [CNCF Paris Meetup 2022-09-15 - VictoriaMetrics - The cost of scale in Prometheus ecosystem](https://www.youtube.com/watch?v=gcZYHpri2Hw). See also [slides](https://docs.google.com/presentation/d/1jhZuKnAXi15M-mdBP5a4ZAiyrMeHhYmzO8xcZ6pMyLc/edit?usp=sharing)
* [Comparing Thanos to VictoriaMetrics cluster](https://faun.pub/comparing-thanos-to-victoriametrics-cluster-b193bea1683) * [Comparing Thanos to VictoriaMetrics cluster](https://faun.pub/comparing-thanos-to-victoriametrics-cluster-b193bea1683)
* [Evaluation performance and correctness: VictoriaMetrics response](https://valyala.medium.com/evaluating-performance-and-correctness-victoriametrics-response-e27315627e87) * [Evaluation performance and correctness: VictoriaMetrics response](https://valyala.medium.com/evaluating-performance-and-correctness-victoriametrics-response-e27315627e87)

View file

@ -15,12 +15,34 @@ The following tip changes can be tested by building VictoriaMetrics components f
## tip ## tip
## [v1.84.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.84.0)
Released at 25-11-2022
* FEATURE: add support for [Pushgateway data import format](https://github.com/prometheus/pushgateway#url) via `/api/v1/import/prometheus` url. See [these docs](https://docs.victoriametrics.com/#how-to-import-data-in-prometheus-exposition-format) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1415). Thanks to @PerGon for [the intial implementation](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3360).
* FEATURE: [VictoriaMetrics cluster](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): add `http://<vmselect>:8481/admin/tenants` API endpoint for returning a list of registered tenants. See [these docs](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#url-format) for details.
* FEATURE: [VictoriaMetrics enterprise](https://docs.victoriametrics.com/enterprise.html): add `-storageNode.filter` command-line flag for filtering the [discovered vmstorage nodes](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery) with arbitrary regular expressions. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3353).
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): allow using numeric values with `K`, `Ki`, `M`, `Mi`, `G`, `Gi`, `T` and `Ti` suffixes inside MetricsQL queries. For example `8Ki` equals to `8*1024`, while `8.2M` equals to `8.2*1000*1000`.
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): add [range_normalize](https://docs.victoriametrics.com/MetricsQL.html#range_normalize) function for normalizing multiple time series into `[0...1]` value range. This function is useful for correlation analysis of time series with distinct value ranges. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3167).
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): add [range_linear_regression](https://docs.victoriametrics.com/MetricsQL.html#range_linear_regression) function for calculating [simple linear regression](https://en.wikipedia.org/wiki/Simple_linear_regression) over the input time series on the selected time range. This function is useful for predictions and capacity planning. For example, `range_linear_regression(process_resident_memory_bytes)` can predict future memory usage based on the past memory usage. * FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): add [range_linear_regression](https://docs.victoriametrics.com/MetricsQL.html#range_linear_regression) function for calculating [simple linear regression](https://en.wikipedia.org/wiki/Simple_linear_regression) over the input time series on the selected time range. This function is useful for predictions and capacity planning. For example, `range_linear_regression(process_resident_memory_bytes)` can predict future memory usage based on the past memory usage.
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): add [range_stddev](https://docs.victoriametrics.com/MetricsQL.html#range_stddev) and [range_stdvar](https://docs.victoriametrics.com/MetricsQL.html#range_stdvar) functions. * FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): add [range_stddev](https://docs.victoriametrics.com/MetricsQL.html#range_stddev) and [range_stdvar](https://docs.victoriametrics.com/MetricsQL.html#range_stdvar) functions.
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): improve structure project, change state management, reduce bundle size, remove Material-UI. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3298) * FEATURE: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): optimize `expr1 op expr2` query when `expr1` returns an empty result. In this case there is no sense in executing `expr2` for `op` not equal to `or`, since the end result will be empty according to [PromQL series matching rules](https://prometheus.io/docs/prometheus/latest/querying/operators/#vector-matching). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3349). Thanks to @jianglinjian for pointing to this case.
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add the ability to upload/paste JSON to investigate the trace. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3308) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3310).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): reduce JS bundle size from 200Kb to 100Kb. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3298).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add the ability to hide results of a particular query by clicking the `eye` icon. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3359).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add copy button to row on Table view. The button copies row in MetricQL format. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2815).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add compact table view. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3241).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add the ability to "stick" a tooltip on the chart by clicking on a data point. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3321) and [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3376)
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add the ability to set up series custom limits. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3297).
* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add default alert list for vmalert's metrics. See [alerts-vmalert.yml](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/deployment/docker/alerts-vmalert.yml).
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): expose `vmagent_relabel_config_*`, `vm_relabel_config_*` and `vm_promscrape_config_*` metrics for tracking relabel and scrape configuration hot-reloads. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3345).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): save the value of the switches "Trace request" and "Disable cache" after page reload. * BUGFIX: [MetricsQL](https://docs.victoriametrics.com/MetricsQL.html): properly return an empty result from [limit_offset](https://docs.victoriametrics.com/MetricsQL.html#limit_offset) if the `offset` arg exceeds the number of inner time series. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3312).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): properly show the tab when navigating from the Prometheus URL in Grafana. * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly discover GCE zones when `filter` option is set at [gce_sd_configs](https://docs.victoriametrics.com/sd_configs.html#gce_sd_configs). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3202).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): properly display the requested graph on the requested time range when navigating from Prometheus URL in Grafana.
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): properly display wide tables. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3153).
* BUGFIX: reduce CPU usage spikes and memory usage spikes under high data ingestion rate introduced in [v1.83.0](https://docs.victoriametrics.com/CHANGELOG.html#v1830). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3343).
## [v1.83.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.83.1) ## [v1.83.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.83.1)

View file

@ -61,6 +61,10 @@ when different tenants have different amounts of data and different query load.
- VictoriaMetrics doesn't support querying multiple tenants in a single request. - VictoriaMetrics doesn't support querying multiple tenants in a single request.
- The list of registered tenants can be obtained via `http://<vmselect>:8481/admin/tenants` url. See [these docs](#url-format).
- VictoriaMetrics exposes various per-tenant statistics via metrics - see [these docs](https://docs.victoriametrics.com/PerTenantStatistic.html).
See also [multitenancy via labels](#multitenancy-via-labels). See also [multitenancy via labels](#multitenancy-via-labels).
@ -215,6 +219,10 @@ For example, `-storageNode='dns+srv:vmstorage-hot' -storageNode='dns+srv:vmstora
It is OK to pass regular static `vmstorage` addresses together with `dns+srv` addresses at `-storageNode`. For example, It is OK to pass regular static `vmstorage` addresses together with `dns+srv` addresses at `-storageNode`. For example,
`-storageNode=vmstorage1,vmstorage2 -storageNode='dns+srv:vmstorage-autodiscovery'`. `-storageNode=vmstorage1,vmstorage2 -storageNode='dns+srv:vmstorage-autodiscovery'`.
The discovered addresses can be filtered with optional `-storageNode.filter` command-line flag, which can contain arbitrary regular expression filter.
For example, `-storageNode.filter='^[^:]+:8400$'` would leave discovered addresses ending with `8400` port only, e.g. the default port used
for sending data from `vminsert` to `vmstorage` node according to `-vminsertAddr` command-line flag.
The currently discovered `vmstorage` nodes can be [monitored](#monitoring) with `vm_rpc_vmstorage_is_reachable` and `vm_rpc_vmstorage_is_read_only` metrics. The currently discovered `vmstorage` nodes can be [monitored](#monitoring) with `vm_rpc_vmstorage_is_reachable` and `vm_rpc_vmstorage_is_read_only` metrics.
## mTLS protection ## mTLS protection
@ -284,7 +292,7 @@ See [troubleshooting docs](https://docs.victoriametrics.com/Troubleshooting.html
- `prometheus/api/v1/import` - for importing data obtained via `api/v1/export` at `vmselect` (see below). - `prometheus/api/v1/import` - for importing data obtained via `api/v1/export` at `vmselect` (see below).
- `prometheus/api/v1/import/native` - for importing data obtained via `api/v1/export/native` on `vmselect` (see below). - `prometheus/api/v1/import/native` - for importing data obtained via `api/v1/export/native` on `vmselect` (see below).
- `prometheus/api/v1/import/csv` - for importing arbitrary CSV data. See [these docs](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-import-csv-data) for details. - `prometheus/api/v1/import/csv` - for importing arbitrary CSV data. See [these docs](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-import-csv-data) for details.
- `prometheus/api/v1/import/prometheus` - for importing data in [Prometheus text exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format) and in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md). See [these docs](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-import-data-in-prometheus-exposition-format) for details. - `prometheus/api/v1/import/prometheus` - for importing data in [Prometheus text exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format) and in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md). This endpoint also supports [Pushgateway protocol](https://github.com/prometheus/pushgateway#url). See [these docs](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-import-data-in-prometheus-exposition-format) for details.
- URLs for [Prometheus querying API](https://prometheus.io/docs/prometheus/latest/querying/api/): `http://<vmselect>:8481/select/<accountID>/prometheus/<suffix>`, where: - URLs for [Prometheus querying API](https://prometheus.io/docs/prometheus/latest/querying/api/): `http://<vmselect>:8481/select/<accountID>/prometheus/<suffix>`, where:
- `<accountID>` is an arbitrary number identifying data namespace for the query (aka tenant) - `<accountID>` is an arbitrary number identifying data namespace for the query (aka tenant)
@ -328,6 +336,9 @@ See [troubleshooting docs](https://docs.victoriametrics.com/Troubleshooting.html
Note that the `delete_series` handler should be used only in exceptional cases such as deletion of accidentally ingested incorrect time series. It shouldn't Note that the `delete_series` handler should be used only in exceptional cases such as deletion of accidentally ingested incorrect time series. It shouldn't
be used on a regular basis, since it carries non-zero overhead. be used on a regular basis, since it carries non-zero overhead.
- URL for listing [tenants](#multitenancy) with the ingested data on the given time range: `http://<vmselect>:8481/admin/tenants?start=...&end=...` .
The `start` and `end` query args are optional. If they are missing, then all the tenants with at least one sample stored in VictoriaMetrics are returned.
- URL for accessing [vmalert's](https://docs.victoriametrics.com/vmalert.html) UI: `http://<vmselect>:8481/select/<accountID>/prometheus/vmalert/`. - URL for accessing [vmalert's](https://docs.victoriametrics.com/vmalert.html) UI: `http://<vmselect>:8481/select/<accountID>/prometheus/vmalert/`.
This URL works only when `-vmalert.proxyURL` flag is set. See more about vmalert [here](#vmalert). This URL works only when `-vmalert.proxyURL` flag is set. See more about vmalert [here](#vmalert).
@ -708,6 +719,8 @@ Report bugs and propose new features [here](https://github.com/VictoriaMetrics/V
Below is the output for `/path/to/vminsert -help`: Below is the output for `/path/to/vminsert -help`:
``` ```
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-cluster.tls -cluster.tls
Whether to use TLS for connections to -storageNode. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection .This flag is available only in enterprise version of VictoriaMetrics Whether to use TLS for connections to -storageNode. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection .This flag is available only in enterprise version of VictoriaMetrics
-cluster.tlsCAFile string -cluster.tlsCAFile string
@ -719,7 +732,7 @@ Below is the output for `/path/to/vminsert -help`:
-cluster.tlsKeyFile string -cluster.tlsKeyFile string
Path to client-side TLS key file to use when connecting to -storageNode if -cluster.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in enterprise version of VictoriaMetrics Path to client-side TLS key file to use when connecting to -storageNode if -cluster.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in enterprise version of VictoriaMetrics
-clusternativeListenAddr string -clusternativeListenAddr string
TCP address to listen for data from other vminsert nodes in multi-level cluster setup. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#multi-level-cluster-setup . Usually :8400 must be set. Doesn't work if empty TCP address to listen for data from other vminsert nodes in multi-level cluster setup. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#multi-level-cluster-setup . Usually :8400 should be set to match default vmstorage port for vminsert. Disabled work if empty
-csvTrimTimestamp duration -csvTrimTimestamp duration
Trim timestamps when importing csv data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms) Trim timestamps when importing csv data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms)
-datadog.maxInsertRequestSize size -datadog.maxInsertRequestSize size
@ -740,7 +753,7 @@ Below is the output for `/path/to/vminsert -help`:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap
@ -833,6 +846,8 @@ Below is the output for `/path/to/vminsert -help`:
Trim timestamps for OpenTSDB HTTP data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms) Trim timestamps for OpenTSDB HTTP data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms)
-pprofAuthKey string -pprofAuthKey string
Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings
-prevCacheRemovalPercent float
Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-pushmetrics.extraLabel array -pushmetrics.extraLabel array
Optional labels to add to metrics pushed to -pushmetrics.url . For example, -pushmetrics.extraLabel='instance="foo"' adds instance="foo" label to all the metrics pushed to -pushmetrics.url Optional labels to add to metrics pushed to -pushmetrics.url . For example, -pushmetrics.extraLabel='instance="foo"' adds instance="foo" label to all the metrics pushed to -pushmetrics.url
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
@ -854,6 +869,8 @@ Below is the output for `/path/to/vminsert -help`:
-storageNode array -storageNode array
Comma-separated addresses of vmstorage nodes; usage: -storageNode=vmstorage-host1,...,vmstorage-hostN . Enterprise version of VictoriaMetrics supports automatic discovery of vmstorage addresses via dns+srv records. For example, -storageNode=dns+srv:vmstorage.addrs . See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery Comma-separated addresses of vmstorage nodes; usage: -storageNode=vmstorage-host1,...,vmstorage-hostN . Enterprise version of VictoriaMetrics supports automatic discovery of vmstorage addresses via dns+srv records. For example, -storageNode=dns+srv:vmstorage.addrs . See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-storageNode.filter string
An optional regexp filter for discovered -storageNode addresses according to https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery. Discovered addresses matching the filter are retained, while other addresses are ignored. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-tls -tls
Whether to enable TLS for incoming HTTP requests at -httpListenAddr (aka https). -tlsCertFile and -tlsKeyFile must be set if -tls is set Whether to enable TLS for incoming HTTP requests at -httpListenAddr (aka https). -tlsCertFile and -tlsKeyFile must be set if -tls is set
-tlsCertFile string -tlsCertFile string
@ -880,6 +897,8 @@ Below is the output for `/path/to/vmselect -help`:
``` ```
-cacheDataPath string -cacheDataPath string
Path to directory for cache files. Cache isn't saved if empty Path to directory for cache files. Cache isn't saved if empty
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-cluster.tls -cluster.tls
Whether to use TLS for connections to -storageNode. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection .This flag is available only in enterprise version of VictoriaMetrics Whether to use TLS for connections to -storageNode. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection .This flag is available only in enterprise version of VictoriaMetrics
-cluster.tlsCAFile string -cluster.tlsCAFile string
@ -912,13 +931,13 @@ Below is the output for `/path/to/vmselect -help`:
-clusternative.tlsKeyFile string -clusternative.tlsKeyFile string
Path to server-side TLS key file to use when accepting connections at -clusternativeListenAddr if -clusternative.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection Path to server-side TLS key file to use when accepting connections at -clusternativeListenAddr if -clusternative.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection
-clusternativeListenAddr string -clusternativeListenAddr string
TCP address to listen for requests from other vmselect nodes in multi-level cluster setup. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#multi-level-cluster-setup . Usually :8401 must be set. Doesn't work if empty TCP address to listen for requests from other vmselect nodes in multi-level cluster setup. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#multi-level-cluster-setup . Usually :8401 should be set to match default vmstorage port for vmselect. Disabled work if empty
-dedup.minScrapeInterval duration -dedup.minScrapeInterval duration
Leave only the last sample in every time series per each discrete interval equal to -dedup.minScrapeInterval > 0. See https://docs.victoriametrics.com/#deduplication for details Leave only the last sample in every time series per each discrete interval equal to -dedup.minScrapeInterval > 0. See https://docs.victoriametrics.com/#deduplication for details
-denyQueryTracing -denyQueryTracing
Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing
-downsampling.period array -downsampling.period array
Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-enableTCP6 -enableTCP6
Whether to enable IPv6 for listening and dialing. By default only IPv4 TCP and UDP is used Whether to enable IPv6 for listening and dialing. By default only IPv4 TCP and UDP is used
@ -927,7 +946,7 @@ Below is the output for `/path/to/vmselect -help`:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap
@ -975,6 +994,8 @@ Below is the output for `/path/to/vmselect -help`:
Auth key for /metrics endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /metrics endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-pprofAuthKey string -pprofAuthKey string
Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings
-prevCacheRemovalPercent float
Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-pushmetrics.extraLabel array -pushmetrics.extraLabel array
Optional labels to add to metrics pushed to -pushmetrics.url . For example, -pushmetrics.extraLabel='instance="foo"' adds instance="foo" label to all the metrics pushed to -pushmetrics.url Optional labels to add to metrics pushed to -pushmetrics.url . For example, -pushmetrics.extraLabel='instance="foo"' adds instance="foo" label to all the metrics pushed to -pushmetrics.url
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
@ -984,7 +1005,7 @@ Below is the output for `/path/to/vmselect -help`:
Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-replicationFactor int -replicationFactor int
How many copies of every time series is available on vmstorage nodes. See -replicationFactor command-line flag for vminsert nodes (default 1) How many copies of every time series is available on vmstorage nodes. vmselect cancels responses from the slowest -replicationFactor-1 vmstorage nodes if -replicationFactor is set by assuming it already received complete data. It isn't recommended setting this flag to values other than 1 at vmselect nodes, since it may result in incomplete responses after adding new vmstorage nodes even if the replication is enabled at vminsert nodes (default 1)
-search.cacheTimestampOffset duration -search.cacheTimestampOffset duration
The maximum duration since the current time for response data, which is always queried from the original raw data, without using the response cache. Increase this value if you see gaps in responses due to time synchronization issues between VictoriaMetrics and data sources (default 5m0s) The maximum duration since the current time for response data, which is always queried from the original raw data, without using the response cache. Increase this value if you see gaps in responses due to time synchronization issues between VictoriaMetrics and data sources (default 5m0s)
-search.denyPartialResponse -search.denyPartialResponse
@ -992,9 +1013,9 @@ Below is the output for `/path/to/vmselect -help`:
-search.disableCache -search.disableCache
Whether to disable response caching. This may be useful during data backfilling Whether to disable response caching. This may be useful during data backfilling
-search.graphiteMaxPointsPerSeries int -search.graphiteMaxPointsPerSeries int
The maximum number of points per series Graphite render API can return. This flag is available only in enterprise version of VictoriaMetrics (default 1000000) The maximum number of points per series Graphite render API can return. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 1000000)
-search.graphiteStorageStep duration -search.graphiteStorageStep duration
The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in enterprise version of VictoriaMetrics (default 10s) The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 10s)
-search.latencyOffset duration -search.latencyOffset duration
The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s) The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s)
-search.logSlowQueryDuration duration -search.logSlowQueryDuration duration
@ -1008,7 +1029,7 @@ Below is the output for `/path/to/vmselect -help`:
-search.maxFederateSeries int -search.maxFederateSeries int
The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000) The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000)
-search.maxGraphiteSeries int -search.maxGraphiteSeries int
The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in enterprise version of VictoriaMetrics (default 300000) The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 300000)
-search.maxLookback duration -search.maxLookback duration
Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons
-search.maxMemoryPerQuery size -search.maxMemoryPerQuery size
@ -1061,8 +1082,10 @@ Below is the output for `/path/to/vmselect -help`:
Comma-separated addresses of vmselect nodes; usage: -selectNode=vmselect-host1,...,vmselect-hostN Comma-separated addresses of vmselect nodes; usage: -selectNode=vmselect-host1,...,vmselect-hostN
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-storageNode array -storageNode array
Comma-separated addresses of vmstorage nodes; usage: -storageNode=vmstorage-host1,...,vmstorage-hostN . Enterprise version of VictoriaMetrics supports automatic discovery of vmstorage addresses via dns+srv records. For example, -storageNode=dns+srv:vmstorage.addrs .See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery Comma-separated addresses of vmstorage nodes; usage: -storageNode=vmstorage-host1,...,vmstorage-hostN . Enterprise version of VictoriaMetrics supports automatic discovery of vmstorage addresses via dns+srv records. For example, -storageNode=dns+srv:vmstorage.addrs . See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-storageNode.filter string
An optional regexp filter for discovered -storageNode addresses according to https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#automatic-vmstorage-discovery. Discovered addresses matching the filter are retained, while other addresses are ignored. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-tls -tls
Whether to enable TLS for incoming HTTP requests at -httpListenAddr (aka https). -tlsCertFile and -tlsKeyFile must be set if -tls is set Whether to enable TLS for incoming HTTP requests at -httpListenAddr (aka https). -tlsCertFile and -tlsKeyFile must be set if -tls is set
-tlsCertFile string -tlsCertFile string
@ -1089,19 +1112,21 @@ Below is the output for `/path/to/vmstorage -help`:
``` ```
-bigMergeConcurrency int -bigMergeConcurrency int
The maximum number of CPU cores to use for big merges. Default value is used if set to 0 The maximum number of CPU cores to use for big merges. Default value is used if set to 0
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-cluster.tls -cluster.tls
Whether to use TLS when accepting connections from vminsert and vmselect. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in enterprise version of VictoriaMetrics Whether to use TLS when accepting connections from vminsert and vmselect. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-cluster.tlsCAFile string -cluster.tlsCAFile string
Path to TLS CA file to use for verifying certificates provided by vminsert and vmselect if -cluster.tls flag is set. By default system CA is used. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in enterprise version of VictoriaMetrics Path to TLS CA file to use for verifying certificates provided by vminsert and vmselect if -cluster.tls flag is set. By default system CA is used. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-cluster.tlsCertFile string -cluster.tlsCertFile string
Path to server-side TLS certificate file to use when accepting connections from vminsert and vmselect if -cluster.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in enterprise version of VictoriaMetrics Path to server-side TLS certificate file to use when accepting connections from vminsert and vmselect if -cluster.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-cluster.tlsCipherSuites array -cluster.tlsCipherSuites array
Optional list of TLS cipher suites used for connections from vminsert and vmselect if -cluster.tls flag is set. See the list of supported cipher suites at https://pkg.go.dev/crypto/tls#pkg-constants .This flag is available only in enterprise version of VictoriaMetrics Optional list of TLS cipher suites used for connections from vminsert and vmselect if -cluster.tls flag is set. See the list of supported cipher suites at https://pkg.go.dev/crypto/tls#pkg-constants .This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-cluster.tlsInsecureSkipVerify -cluster.tlsInsecureSkipVerify
Whether to skip verification of TLS certificates provided by vminsert and vmselect if -cluster.tls flag is set. Note that disabled TLS certificate verification breaks security. This flag is available only in enterprise version of VictoriaMetrics Whether to skip verification of TLS certificates provided by vminsert and vmselect if -cluster.tls flag is set. Note that disabled TLS certificate verification breaks security. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-cluster.tlsKeyFile string -cluster.tlsKeyFile string
Path to server-side TLS key file to use when accepting connections from vminsert and vmselect if -cluster.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in enterprise version of VictoriaMetrics Path to server-side TLS key file to use when accepting connections from vminsert and vmselect if -cluster.tls flag is set. See https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#mtls-protection . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-dedup.minScrapeInterval duration -dedup.minScrapeInterval duration
Leave only the last sample in every time series per each discrete interval equal to -dedup.minScrapeInterval > 0. See https://docs.victoriametrics.com/#deduplication for details Leave only the last sample in every time series per each discrete interval equal to -dedup.minScrapeInterval > 0. See https://docs.victoriametrics.com/#deduplication for details
-denyQueriesOutsideRetention -denyQueriesOutsideRetention
@ -1109,7 +1134,7 @@ Below is the output for `/path/to/vmstorage -help`:
-denyQueryTracing -denyQueryTracing
Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing
-downsampling.period array -downsampling.period array
Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-enableTCP6 -enableTCP6
Whether to enable IPv6 for listening and dialing. By default only IPv4 TCP and UDP is used Whether to enable IPv6 for listening and dialing. By default only IPv4 TCP and UDP is used
@ -1118,7 +1143,7 @@ Below is the output for `/path/to/vmstorage -help`:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-finalMergeDelay duration -finalMergeDelay duration
The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge
-flagsAuthKey string -flagsAuthKey string
@ -1175,7 +1200,7 @@ Below is the output for `/path/to/vmstorage -help`:
-precisionBits int -precisionBits int
The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64) The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64)
-prevCacheRemovalPercent float -prevCacheRemovalPercent float
The previous cache is removed when the percent of requests it serves becomes lower than this value. Higher values reduce average memory usage at the cost of higher CPU usage (default 0.2) Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-pushmetrics.extraLabel array -pushmetrics.extraLabel array
Optional labels to add to metrics pushed to -pushmetrics.url . For example, -pushmetrics.extraLabel='instance="foo"' adds instance="foo" label to all the metrics pushed to -pushmetrics.url Optional labels to add to metrics pushed to -pushmetrics.url . For example, -pushmetrics.extraLabel='instance="foo"' adds instance="foo" label to all the metrics pushed to -pushmetrics.url
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
@ -1185,7 +1210,7 @@ Below is the output for `/path/to/vmstorage -help`:
Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-retentionFilter array -retentionFilter array
Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in enterprise version of VictoriaMetrics Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-retentionPeriod value -retentionPeriod value
Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter

View file

@ -73,6 +73,7 @@ The list of MetricsQL features:
* The duration suffix is optional. The duration is in seconds if the suffix is missing. * The duration suffix is optional. The duration is in seconds if the suffix is missing.
For example, `rate(m[300] offset 1800)` is equivalent to `rate(m[5m]) offset 30m`. For example, `rate(m[300] offset 1800)` is equivalent to `rate(m[5m]) offset 30m`.
* The duration can be placed anywhere in the query. For example, `sum_over_time(m[1h]) / 1h` is equivalent to `sum_over_time(m[1h]) / 3600`. * The duration can be placed anywhere in the query. For example, `sum_over_time(m[1h]) / 1h` is equivalent to `sum_over_time(m[1h]) / 3600`.
* Numeric values can have `K`, `Ki`, `M`, `Mi`, `G`, `Gi`, `T` and `Ti` suffixes. For example, `8K` is equivalent to `8000`, while `1.2Mi` is equvalent to `1.2*1024*1024`.
* Trailing commas on all the lists are allowed - label filters, function args and with expressions. * Trailing commas on all the lists are allowed - label filters, function args and with expressions.
For instance, the following queries are valid: `m{foo="bar",}`, `f(a, b,)`, `WITH (x=y,) x`. For instance, the following queries are valid: `m{foo="bar",}`, `f(a, b,)`, `WITH (x=y,) x`.
This simplifies maintenance of multi-line queries. This simplifies maintenance of multi-line queries.
@ -1051,6 +1052,8 @@ See also [histogram_quantile](#histogram_quantile).
`histogram_share(le, buckets)` is a [transform function](#transform-functions), which calculates the share (in the range `[0...1]`) `histogram_share(le, buckets)` is a [transform function](#transform-functions), which calculates the share (in the range `[0...1]`)
for `buckets` that fall below `le`. This function is useful for calculating SLI and SLO. This is inverse to [histogram_quantile](#histogram_quantile). for `buckets` that fall below `le`. This function is useful for calculating SLI and SLO. This is inverse to [histogram_quantile](#histogram_quantile).
The function accepts optional third arg - `boundsLabel`. In this case it returns `lower` and `upper` bounds for the estimated share with the given `boundsLabel` label.
#### histogram_stddev #### histogram_stddev
`histogram_stddev(buckets)` is a [transform function](#transform-functions), which calculates standard deviation for the given `buckets`. `histogram_stddev(buckets)` is a [transform function](#transform-functions), which calculates standard deviation for the given `buckets`.
@ -1220,6 +1223,11 @@ over the selected time range per each time series returned by `q`. This function
`range_min(q)` is a [transform function](#transform-functions), which calculates the min value across points per each time series returned by `q`. `range_min(q)` is a [transform function](#transform-functions), which calculates the min value across points per each time series returned by `q`.
#### range_normalize
`range_normalize(q1, ...)` is a [transform function](#transform-functions), which normalizes values for time series returned by `q1, ...` into `[0 ... 1]` range.
This function is useful for correlating time series with distinct value ranges.
#### range_quantile #### range_quantile
`range_quantile(phi, q)` is a [transform function](#transform-functions), which returns `phi`-quantile across points per each time series returned by `q`. `range_quantile(phi, q)` is a [transform function](#transform-functions), which returns `phi`-quantile across points per each time series returned by `q`.

View file

@ -290,7 +290,10 @@ When querying the [backfilled data](https://docs.victoriametrics.com/#backfillin
VMUI automatically adjusts the interval between datapoints on the graph depending on the horizontal resolution and on the selected time range. The step value can be customized by changing `Step value` input. VMUI automatically adjusts the interval between datapoints on the graph depending on the horizontal resolution and on the selected time range. The step value can be customized by changing `Step value` input.
VMUI allows investigating correlations between multiple queries on the same graph. Just click `Add Query` button, enter an additional query in the newly appeared input field and press `Ctrl+Enter`. Results for all the queries should be displayed simultaneously on the same graph. VMUI allows investigating correlations between multiple queries on the same graph. Just click `Add Query` button,
enter an additional query in the newly appeared input field and press `Enter`.
Results for all the queries are displayed simultaneously on the same graph.
Graphs for a particular query can be temporarily hidden by clicking the `eye` icon on the right side of the input field.
See the [example VMUI at VictoriaMetrics playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/?g0.expr=100%20*%20sum(rate(process_cpu_seconds_total))%20by%20(job)&g0.range_input=1d). See the [example VMUI at VictoriaMetrics playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/?g0.expr=100%20*%20sum(rate(process_cpu_seconds_total))%20by%20(job)&g0.range_input=1d).
@ -1046,7 +1049,8 @@ Time series data can be imported into VictoriaMetrics via any supported data ing
* `/api/v1/import/native` for importing data obtained from [/api/v1/export/native](#how-to-export-data-in-native-format). * `/api/v1/import/native` for importing data obtained from [/api/v1/export/native](#how-to-export-data-in-native-format).
See [these docs](#how-to-import-data-in-native-format) for details. See [these docs](#how-to-import-data-in-native-format) for details.
* `/api/v1/import/csv` for importing arbitrary CSV data. See [these docs](#how-to-import-csv-data) for details. * `/api/v1/import/csv` for importing arbitrary CSV data. See [these docs](#how-to-import-csv-data) for details.
* `/api/v1/import/prometheus` for importing data in Prometheus exposition format. See [these docs](#how-to-import-data-in-prometheus-exposition-format) for details. * `/api/v1/import/prometheus` for importing data in Prometheus exposition format and in [Pushgateway format](https://github.com/prometheus/pushgateway#url).
See [these docs](#how-to-import-data-in-prometheus-exposition-format) for details.
### How to import data in JSON line format ### How to import data in JSON line format
@ -1151,9 +1155,11 @@ Note that it could be required to flush response cache after importing historica
### How to import data in Prometheus exposition format ### How to import data in Prometheus exposition format
VictoriaMetrics accepts data in [Prometheus exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format) VictoriaMetrics accepts data in [Prometheus exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format),
and in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md) in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md)
via `/api/v1/import/prometheus` path. For example, the following line imports a single line in Prometheus exposition format into VictoriaMetrics: and in [Pushgateway format](https://github.com/prometheus/pushgateway#url) via `/api/v1/import/prometheus` path.
For example, the following command imports a single line in Prometheus exposition format into VictoriaMetrics:
<div class="with-copy" markdown="1"> <div class="with-copy" markdown="1">
@ -1179,6 +1185,16 @@ It should return something like the following:
{"metric":{"__name__":"foo","bar":"baz"},"values":[123],"timestamps":[1594370496905]} {"metric":{"__name__":"foo","bar":"baz"},"values":[123],"timestamps":[1594370496905]}
``` ```
The following command imports a single metric via [Pushgateway format](https://github.com/prometheus/pushgateway#url) with `{job="my_app",instance="host123"}` labels:
<div class="with-copy" markdown="1">
```console
curl -d 'metric{label="abc"} 123' -X POST 'http://localhost:8428/api/v1/import/prometheus/metrics/job/my_app/instance/host123'
```
</div>
Pass `Content-Encoding: gzip` HTTP request header to `/api/v1/import/prometheus` for importing gzipped data: Pass `Content-Encoding: gzip` HTTP request header to `/api/v1/import/prometheus` for importing gzipped data:
<div class="with-copy" markdown="1"> <div class="with-copy" markdown="1">
@ -1190,8 +1206,8 @@ curl -X POST -H 'Content-Encoding: gzip' http://destination-victoriametrics:8428
</div> </div>
Extra labels may be added to all the imported metrics by passing `extra_label=name=value` query args. Extra labels may be added to all the imported metrics either via [Pushgateway format](https://github.com/prometheus/pushgateway#url)
For example, `/api/v1/import/prometheus?extra_label=foo=bar` would add `{foo="bar"}` label to all the imported metrics. or by passing `extra_label=name=value` query args. For example, `/api/v1/import/prometheus?extra_label=foo=bar` would add `{foo="bar"}` label to all the imported metrics.
If timestamp is missing in `<metric> <value> <timestamp>` Prometheus exposition format line, then the current timestamp is used during data ingestion. If timestamp is missing in `<metric> <value> <timestamp>` Prometheus exposition format line, then the current timestamp is used during data ingestion.
It can be overridden by passing unix timestamp in *milliseconds* via `timestamp` query arg. For example, `/api/v1/import/prometheus?timestamp=1594370496905`. It can be overridden by passing unix timestamp in *milliseconds* via `timestamp` query arg. For example, `/api/v1/import/prometheus?timestamp=1594370496905`.
@ -1642,7 +1658,9 @@ All the durations and timestamps in traces are in milliseconds.
Query tracing is allowed by default. It can be denied by passing `-denyQueryTracing` command-line flag to VictoriaMetrics. Query tracing is allowed by default. It can be denied by passing `-denyQueryTracing` command-line flag to VictoriaMetrics.
[VMUI](#vmui) provides an UI for query tracing - just click `Trace query` checkbox and re-run the query in order to investigate its' trace. [VMUI](#vmui) provides an UI:
- for query tracing - just click `Trace query` checkbox and re-run the query in order to investigate its' trace.
- for exploring custom trace - go to the tab `Trace analyzer` and upload or paste JSON with trace information.
## Cardinality limiter ## Cardinality limiter
@ -2031,6 +2049,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
``` ```
-bigMergeConcurrency int -bigMergeConcurrency int
The maximum number of CPU cores to use for big merges. Default value is used if set to 0 The maximum number of CPU cores to use for big merges. Default value is used if set to 0
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-configAuthKey string -configAuthKey string
Authorization key for accessing /config page. It must be passed via authKey query arg Authorization key for accessing /config page. It must be passed via authKey query arg
-csvTrimTimestamp duration -csvTrimTimestamp duration
@ -2049,7 +2069,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-denyQueryTracing -denyQueryTracing
Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing
-downsampling.period array -downsampling.period array
Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in enterprise version of VictoriaMetrics Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-dryRun -dryRun
Whether to check only -promscrape.config and then exit. Unknown config entries aren't allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse=false command-line flag Whether to check only -promscrape.config and then exit. Unknown config entries aren't allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse=false command-line flag
@ -2060,7 +2080,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-finalMergeDelay duration -finalMergeDelay duration
The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge
-flagsAuthKey string -flagsAuthKey string
@ -2163,6 +2183,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings
-precisionBits int -precisionBits int
The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64) The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64)
-prevCacheRemovalPercent float
Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-promscrape.azureSDCheckInterval duration -promscrape.azureSDCheckInterval duration
Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s) Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s)
-promscrape.cluster.memberNum string -promscrape.cluster.memberNum string
@ -2257,7 +2279,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-relabelDebug -relabelDebug
Whether to log metrics before and after relabeling with -relabelConfig. If the -relabelDebug is enabled, then the metrics aren't sent to storage. This is useful for debugging the relabeling configs Whether to log metrics before and after relabeling with -relabelConfig. If the -relabelDebug is enabled, then the metrics aren't sent to storage. This is useful for debugging the relabeling configs
-retentionFilter array -retentionFilter array
Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in enterprise version of VictoriaMetrics Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-retentionPeriod value -retentionPeriod value
Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter
@ -2271,9 +2293,9 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-search.disableCache -search.disableCache
Whether to disable response caching. This may be useful during data backfilling Whether to disable response caching. This may be useful during data backfilling
-search.graphiteMaxPointsPerSeries int -search.graphiteMaxPointsPerSeries int
The maximum number of points per series Graphite render API can return. This flag is available only in enterprise version of VictoriaMetrics (default 1000000) The maximum number of points per series Graphite render API can return. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 1000000)
-search.graphiteStorageStep duration -search.graphiteStorageStep duration
The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in enterprise version of VictoriaMetrics (default 10s) The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 10s)
-search.latencyOffset duration -search.latencyOffset duration
The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s) The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s)
-search.logSlowQueryDuration duration -search.logSlowQueryDuration duration
@ -2287,7 +2309,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-search.maxFederateSeries int -search.maxFederateSeries int
The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000) The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000)
-search.maxGraphiteSeries int -search.maxGraphiteSeries int
The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in enterprise version of VictoriaMetrics (default 300000) The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 300000)
-search.maxLookback duration -search.maxLookback duration
Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons
-search.maxMemoryPerQuery size -search.maxMemoryPerQuery size

View file

@ -293,7 +293,10 @@ When querying the [backfilled data](https://docs.victoriametrics.com/#backfillin
VMUI automatically adjusts the interval between datapoints on the graph depending on the horizontal resolution and on the selected time range. The step value can be customized by changing `Step value` input. VMUI automatically adjusts the interval between datapoints on the graph depending on the horizontal resolution and on the selected time range. The step value can be customized by changing `Step value` input.
VMUI allows investigating correlations between multiple queries on the same graph. Just click `Add Query` button, enter an additional query in the newly appeared input field and press `Ctrl+Enter`. Results for all the queries should be displayed simultaneously on the same graph. VMUI allows investigating correlations between multiple queries on the same graph. Just click `Add Query` button,
enter an additional query in the newly appeared input field and press `Enter`.
Results for all the queries are displayed simultaneously on the same graph.
Graphs for a particular query can be temporarily hidden by clicking the `eye` icon on the right side of the input field.
See the [example VMUI at VictoriaMetrics playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/?g0.expr=100%20*%20sum(rate(process_cpu_seconds_total))%20by%20(job)&g0.range_input=1d). See the [example VMUI at VictoriaMetrics playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/?g0.expr=100%20*%20sum(rate(process_cpu_seconds_total))%20by%20(job)&g0.range_input=1d).
@ -1049,7 +1052,8 @@ Time series data can be imported into VictoriaMetrics via any supported data ing
* `/api/v1/import/native` for importing data obtained from [/api/v1/export/native](#how-to-export-data-in-native-format). * `/api/v1/import/native` for importing data obtained from [/api/v1/export/native](#how-to-export-data-in-native-format).
See [these docs](#how-to-import-data-in-native-format) for details. See [these docs](#how-to-import-data-in-native-format) for details.
* `/api/v1/import/csv` for importing arbitrary CSV data. See [these docs](#how-to-import-csv-data) for details. * `/api/v1/import/csv` for importing arbitrary CSV data. See [these docs](#how-to-import-csv-data) for details.
* `/api/v1/import/prometheus` for importing data in Prometheus exposition format. See [these docs](#how-to-import-data-in-prometheus-exposition-format) for details. * `/api/v1/import/prometheus` for importing data in Prometheus exposition format and in [Pushgateway format](https://github.com/prometheus/pushgateway#url).
See [these docs](#how-to-import-data-in-prometheus-exposition-format) for details.
### How to import data in JSON line format ### How to import data in JSON line format
@ -1154,9 +1158,11 @@ Note that it could be required to flush response cache after importing historica
### How to import data in Prometheus exposition format ### How to import data in Prometheus exposition format
VictoriaMetrics accepts data in [Prometheus exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format) VictoriaMetrics accepts data in [Prometheus exposition format](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-based-format),
and in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md) in [OpenMetrics format](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md)
via `/api/v1/import/prometheus` path. For example, the following line imports a single line in Prometheus exposition format into VictoriaMetrics: and in [Pushgateway format](https://github.com/prometheus/pushgateway#url) via `/api/v1/import/prometheus` path.
For example, the following command imports a single line in Prometheus exposition format into VictoriaMetrics:
<div class="with-copy" markdown="1"> <div class="with-copy" markdown="1">
@ -1182,6 +1188,16 @@ It should return something like the following:
{"metric":{"__name__":"foo","bar":"baz"},"values":[123],"timestamps":[1594370496905]} {"metric":{"__name__":"foo","bar":"baz"},"values":[123],"timestamps":[1594370496905]}
``` ```
The following command imports a single metric via [Pushgateway format](https://github.com/prometheus/pushgateway#url) with `{job="my_app",instance="host123"}` labels:
<div class="with-copy" markdown="1">
```console
curl -d 'metric{label="abc"} 123' -X POST 'http://localhost:8428/api/v1/import/prometheus/metrics/job/my_app/instance/host123'
```
</div>
Pass `Content-Encoding: gzip` HTTP request header to `/api/v1/import/prometheus` for importing gzipped data: Pass `Content-Encoding: gzip` HTTP request header to `/api/v1/import/prometheus` for importing gzipped data:
<div class="with-copy" markdown="1"> <div class="with-copy" markdown="1">
@ -1193,8 +1209,8 @@ curl -X POST -H 'Content-Encoding: gzip' http://destination-victoriametrics:8428
</div> </div>
Extra labels may be added to all the imported metrics by passing `extra_label=name=value` query args. Extra labels may be added to all the imported metrics either via [Pushgateway format](https://github.com/prometheus/pushgateway#url)
For example, `/api/v1/import/prometheus?extra_label=foo=bar` would add `{foo="bar"}` label to all the imported metrics. or by passing `extra_label=name=value` query args. For example, `/api/v1/import/prometheus?extra_label=foo=bar` would add `{foo="bar"}` label to all the imported metrics.
If timestamp is missing in `<metric> <value> <timestamp>` Prometheus exposition format line, then the current timestamp is used during data ingestion. If timestamp is missing in `<metric> <value> <timestamp>` Prometheus exposition format line, then the current timestamp is used during data ingestion.
It can be overridden by passing unix timestamp in *milliseconds* via `timestamp` query arg. For example, `/api/v1/import/prometheus?timestamp=1594370496905`. It can be overridden by passing unix timestamp in *milliseconds* via `timestamp` query arg. For example, `/api/v1/import/prometheus?timestamp=1594370496905`.
@ -1645,7 +1661,9 @@ All the durations and timestamps in traces are in milliseconds.
Query tracing is allowed by default. It can be denied by passing `-denyQueryTracing` command-line flag to VictoriaMetrics. Query tracing is allowed by default. It can be denied by passing `-denyQueryTracing` command-line flag to VictoriaMetrics.
[VMUI](#vmui) provides an UI for query tracing - just click `Trace query` checkbox and re-run the query in order to investigate its' trace. [VMUI](#vmui) provides an UI:
- for query tracing - just click `Trace query` checkbox and re-run the query in order to investigate its' trace.
- for exploring custom trace - go to the tab `Trace analyzer` and upload or paste JSON with trace information.
## Cardinality limiter ## Cardinality limiter
@ -2034,6 +2052,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
``` ```
-bigMergeConcurrency int -bigMergeConcurrency int
The maximum number of CPU cores to use for big merges. Default value is used if set to 0 The maximum number of CPU cores to use for big merges. Default value is used if set to 0
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-configAuthKey string -configAuthKey string
Authorization key for accessing /config page. It must be passed via authKey query arg Authorization key for accessing /config page. It must be passed via authKey query arg
-csvTrimTimestamp duration -csvTrimTimestamp duration
@ -2052,7 +2072,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-denyQueryTracing -denyQueryTracing
Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing Whether to disable the ability to trace queries. See https://docs.victoriametrics.com/#query-tracing
-downsampling.period array -downsampling.period array
Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in enterprise version of VictoriaMetrics Comma-separated downsampling periods in the format 'offset:period'. For example, '30d:10m' instructs to leave a single sample per 10 minutes for samples older than 30 days. See https://docs.victoriametrics.com/#downsampling for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-dryRun -dryRun
Whether to check only -promscrape.config and then exit. Unknown config entries aren't allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse=false command-line flag Whether to check only -promscrape.config and then exit. Unknown config entries aren't allowed in -promscrape.config by default. This can be changed with -promscrape.config.strictParse=false command-line flag
@ -2063,7 +2083,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-finalMergeDelay duration -finalMergeDelay duration
The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge The delay before starting final merge for per-month partition after no new data is ingested into it. Final merge may require additional disk IO and CPU resources. Final merge may increase query speed and reduce disk space usage in some cases. Zero value disables final merge
-flagsAuthKey string -flagsAuthKey string
@ -2166,6 +2186,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings
-precisionBits int -precisionBits int
The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64) The number of precision bits to store per each value. Lower precision bits improves data compression at the cost of precision loss (default 64)
-prevCacheRemovalPercent float
Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-promscrape.azureSDCheckInterval duration -promscrape.azureSDCheckInterval duration
Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s) Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s)
-promscrape.cluster.memberNum string -promscrape.cluster.memberNum string
@ -2260,7 +2282,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-relabelDebug -relabelDebug
Whether to log metrics before and after relabeling with -relabelConfig. If the -relabelDebug is enabled, then the metrics aren't sent to storage. This is useful for debugging the relabeling configs Whether to log metrics before and after relabeling with -relabelConfig. If the -relabelDebug is enabled, then the metrics aren't sent to storage. This is useful for debugging the relabeling configs
-retentionFilter array -retentionFilter array
Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in enterprise version of VictoriaMetrics Retention filter in the format 'filter:retention'. For example, '{env="dev"}:3d' configures the retention for time series with env="dev" label to 3 days. See https://docs.victoriametrics.com/#retention-filters for details. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-retentionPeriod value -retentionPeriod value
Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter Data with timestamps outside the retentionPeriod is automatically deleted. See also -retentionFilter
@ -2274,9 +2296,9 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-search.disableCache -search.disableCache
Whether to disable response caching. This may be useful during data backfilling Whether to disable response caching. This may be useful during data backfilling
-search.graphiteMaxPointsPerSeries int -search.graphiteMaxPointsPerSeries int
The maximum number of points per series Graphite render API can return. This flag is available only in enterprise version of VictoriaMetrics (default 1000000) The maximum number of points per series Graphite render API can return. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 1000000)
-search.graphiteStorageStep duration -search.graphiteStorageStep duration
The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in enterprise version of VictoriaMetrics (default 10s) The interval between datapoints stored in the database. It is used at Graphite Render API handler for normalizing the interval between datapoints in case it isn't normalized. It can be overridden by sending 'storage_step' query arg to /render API or by sending the desired interval via 'Storage-Step' http header during querying /render API. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 10s)
-search.latencyOffset duration -search.latencyOffset duration
The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s) The time when data points become visible in query results after the collection. Too small value can result in incomplete last points for query results (default 30s)
-search.logSlowQueryDuration duration -search.logSlowQueryDuration duration
@ -2290,7 +2312,7 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
-search.maxFederateSeries int -search.maxFederateSeries int
The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000) The maximum number of time series, which can be returned from /federate. This option allows limiting memory usage (default 1000000)
-search.maxGraphiteSeries int -search.maxGraphiteSeries int
The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in enterprise version of VictoriaMetrics (default 300000) The maximum number of time series, which can be scanned during queries to Graphite Render API. See https://docs.victoriametrics.com/#graphite-render-api-usage . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default 300000)
-search.maxLookback duration -search.maxLookback duration
Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons Synonym to -search.lookback-delta from Prometheus. The value is dynamically detected from interval between time series datapoints if not set. It can be overridden on per-query basis via max_lookback arg. See also '-search.maxStalenessInterval' flag, which has the same meaining due to historical reasons
-search.maxMemoryPerQuery size -search.maxMemoryPerQuery size

View file

@ -549,7 +549,7 @@ The following articles contain useful information about Prometheus relabeling:
* `keep_metrics`: keeps all the metrics with names matching the given `regex`, * `keep_metrics`: keeps all the metrics with names matching the given `regex`,
while dropping all the other metrics. For example, the following relabeling config keeps metrics while dropping all the other metrics. For example, the following relabeling config keeps metrics
with `fo` and `bar` names, while dropping all the other metrics: with `foo` and `bar` names, while dropping all the other metrics:
```yaml ```yaml
- action: keep_metrics - action: keep_metrics
@ -1111,6 +1111,8 @@ vmagent collects metrics data via popular data ingestion protocols and routes th
See the docs at https://docs.victoriametrics.com/vmagent.html . See the docs at https://docs.victoriametrics.com/vmagent.html .
-cacheExpireDuration duration
Items are removed from in-memory caches after they aren't accessed for this duration. Lower values may reduce memory usage at the cost of higher CPU usage. See also -prevCacheRemovalPercent (default 30m0s)
-configAuthKey string -configAuthKey string
Authorization key for accessing /config page. It must be passed via authKey query arg Authorization key for accessing /config page. It must be passed via authKey query arg
-csvTrimTimestamp duration -csvTrimTimestamp duration
@ -1131,7 +1133,7 @@ See the docs at https://docs.victoriametrics.com/vmagent.html .
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap
@ -1182,30 +1184,30 @@ See the docs at https://docs.victoriametrics.com/vmagent.html .
-insert.maxQueueDuration duration -insert.maxQueueDuration duration
The maximum duration for waiting in the queue for insert requests due to -maxConcurrentInserts (default 1m0s) The maximum duration for waiting in the queue for insert requests due to -maxConcurrentInserts (default 1m0s)
-kafka.consumer.topic array -kafka.consumer.topic array
Kafka topic names for data consumption. This flag is available only in enterprise version of VictoriaMetrics Kafka topic names for data consumption. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.basicAuth.password array -kafka.consumer.topic.basicAuth.password array
Optional basic auth password for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in enterprise version of VictoriaMetrics Optional basic auth password for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.basicAuth.username array -kafka.consumer.topic.basicAuth.username array
Optional basic auth username for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in enterprise version of VictoriaMetrics Optional basic auth username for -kafka.consumer.topic. Must be used in conjunction with any supported auth methods for kafka client, specified by flag -kafka.consumer.topic.options='security.protocol=SASL_SSL;sasl.mechanisms=PLAIN' . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.brokers array -kafka.consumer.topic.brokers array
List of brokers to connect for given topic, e.g. -kafka.consumer.topic.broker=host-1:9092;host-2:9092 . This flag is available only in enterprise version of VictoriaMetrics List of brokers to connect for given topic, e.g. -kafka.consumer.topic.broker=host-1:9092;host-2:9092 . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.defaultFormat string -kafka.consumer.topic.defaultFormat string
Expected data format in the topic if -kafka.consumer.topic.format is skipped. This flag is available only in enterprise version of VictoriaMetrics (default "promremotewrite") Expected data format in the topic if -kafka.consumer.topic.format is skipped. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html (default "promremotewrite")
-kafka.consumer.topic.format array -kafka.consumer.topic.format array
data format for corresponding kafka topic. Valid formats: influx, prometheus, promremotewrite, graphite, jsonline . This flag is available only in enterprise version of VictoriaMetrics data format for corresponding kafka topic. Valid formats: influx, prometheus, promremotewrite, graphite, jsonline . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.groupID array -kafka.consumer.topic.groupID array
Defines group.id for topic. This flag is available only in enterprise version of VictoriaMetrics Defines group.id for topic. This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.isGzipped array -kafka.consumer.topic.isGzipped array
Enables gzip setting for topic messages payload. Only prometheus, jsonline and influx formats accept gzipped messages.This flag is available only in enterprise version of VictoriaMetrics Enables gzip setting for topic messages payload. Only prometheus, jsonline and influx formats accept gzipped messages.This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports array of values separated by comma or specified via multiple flags. Supports array of values separated by comma or specified via multiple flags.
-kafka.consumer.topic.options array -kafka.consumer.topic.options array
Optional key=value;key1=value2 settings for topic consumer. See full configuration options at https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md . This flag is available only in enterprise version of VictoriaMetrics Optional key=value;key1=value2 settings for topic consumer. See full configuration options at https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-loggerDisableTimestamps -loggerDisableTimestamps
Whether to disable writing timestamps in logs Whether to disable writing timestamps in logs
@ -1246,6 +1248,8 @@ See the docs at https://docs.victoriametrics.com/vmagent.html .
Trim timestamps for OpenTSDB HTTP data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms) Trim timestamps for OpenTSDB HTTP data to this duration. Minimum practical duration is 1ms. Higher duration (i.e. 1s) may be used for reducing disk space usage for timestamp data (default 1ms)
-pprofAuthKey string -pprofAuthKey string
Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /debug/pprof/* endpoints. It must be passed via authKey query arg. It overrides httpAuth.* settings
-prevCacheRemovalPercent float
Items in the previous caches are removed when the percent of requests it serves becomes lower than this value. Higher values reduce memory usage at the cost of higher CPU usage. See also -cacheExpireDuration (default 0.1)
-promscrape.azureSDCheckInterval duration -promscrape.azureSDCheckInterval duration
Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s) Interval for checking for changes in Azure. This works only if azure_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#azure_sd_configs for details (default 1m0s)
-promscrape.cluster.memberNum string -promscrape.cluster.memberNum string

View file

@ -677,10 +677,12 @@ See full description for these flags in `./vmalert -help`.
## Monitoring ## Monitoring
`vmalert` exports various metrics in Prometheus exposition format at `http://vmalert-host:8880/metrics` page. `vmalert` exports various metrics in Prometheus exposition format at `http://vmalert-host:8880/metrics` page.
The default list of alerting rules for these metric can be found [here](https://github.com/VictoriaMetrics/VictoriaMetrics/tree/master/deployment/docker).
We recommend setting up regular scraping of this page either through `vmagent` or by Prometheus so that the exported We recommend setting up regular scraping of this page either through `vmagent` or by Prometheus so that the exported
metrics may be analyzed later. metrics may be analyzed later.
Use the official [Grafana dashboard](https://grafana.com/grafana/dashboards/14950) for `vmalert` overview. Graphs on this dashboard contain useful hints - hover the `i` icon at the top left corner of each graph in order to read it. Use the official [Grafana dashboard](https://grafana.com/grafana/dashboards/14950) for `vmalert` overview.
Graphs on this dashboard contain useful hints - hover the `i` icon in the top left corner of each graph in order to read it.
If you have suggestions for improvements or have found a bug - please open an issue on github or add If you have suggestions for improvements or have found a bug - please open an issue on github or add
a review to the dashboard. a review to the dashboard.
@ -785,7 +787,7 @@ The shortlist of configuration flags is the following:
{% raw %} {% raw %}
``` ```
-clusterMode -clusterMode
If clusterMode is enabled, then vmalert automatically adds the tenant specified in config groups to -datasource.url, -remoteWrite.url and -remoteRead.url. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in enterprise version of VictoriaMetrics If clusterMode is enabled, then vmalert automatically adds the tenant specified in config groups to -datasource.url, -remoteWrite.url and -remoteRead.url. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-configCheckInterval duration -configCheckInterval duration
Interval for checking for changes in '-rule' or '-notifier.config' files. By default the checking is disabled. Send SIGHUP signal in order to force config check for changes. Interval for checking for changes in '-rule' or '-notifier.config' files. By default the checking is disabled. Send SIGHUP signal in order to force config check for changes.
-datasource.appendTypePrefix -datasource.appendTypePrefix
@ -839,9 +841,9 @@ The shortlist of configuration flags is the following:
-datasource.url string -datasource.url string
Datasource compatible with Prometheus HTTP API. It can be single node VictoriaMetrics or vmselect URL. Required parameter. E.g. http://127.0.0.1:8428 . See also '-datasource.disablePathAppend', '-datasource.showURL'. Datasource compatible with Prometheus HTTP API. It can be single node VictoriaMetrics or vmselect URL. Required parameter. E.g. http://127.0.0.1:8428 . See also '-datasource.disablePathAppend', '-datasource.showURL'.
-defaultTenant.graphite string -defaultTenant.graphite string
Default tenant for Graphite alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy .This flag is available only in enterprise version of VictoriaMetrics Default tenant for Graphite alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy .This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-defaultTenant.prometheus string -defaultTenant.prometheus string
Default tenant for Prometheus alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in enterprise version of VictoriaMetrics Default tenant for Prometheus alerting groups. See https://docs.victoriametrics.com/vmalert.html#multitenancy . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-disableAlertgroupLabel -disableAlertgroupLabel
Whether to disable adding group's Name as label to generated alerts and time series. Whether to disable adding group's Name as label to generated alerts and time series.
-dryRun -dryRun
@ -853,12 +855,11 @@ The shortlist of configuration flags is the following:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-evaluationInterval duration -evaluationInterval duration
How often to evaluate the rules (default 1m0s) How often to evaluate the rules (default 1m0s)
-external.alert.source string -external.alert.source string
External Alert Source allows to override the Source link for alerts sent to AlertManager for cases where you want to build a custom link to Grafana, Prometheus or any other service. Supports templating - see https://docs.victoriametrics.com/vmalert.html#templating . For example, link to Grafana: -external.alert.source='explore?orgId=1&left=["now-1h","now","VictoriaMetrics",{"expr":{{$expr|jsonEscape|queryEscape}} },{"mode":"Metrics"},{"ui":[true,true,true,"none"]}]' . If empty 'vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}' is used External Alert Source allows to override the Source link for alerts sent to AlertManager for cases where you want to build a custom link to Grafana, Prometheus or any other service. Supports templating - see https://docs.victoriametrics.com/vmalert.html#templating . For example, link to Grafana: -external.alert.source='explore?orgId=1&left=["now-1h","now","VictoriaMetrics",{"expr":{{$expr|jsonEscape|queryEscape}} },{"mode":"Metrics"},{"ui":[true,true,true,"none"]}]' . If empty 'vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}' is used.
If empty 'vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}' is used.
-external.label array -external.label array
Optional label in the form 'Name=value' to add to all generated recording rules and alerts. Pass multiple -label flags in order to add multiple label sets. Optional label in the form 'Name=value' to add to all generated recording rules and alerts. Pass multiple -label flags in order to add multiple label sets.
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.

View file

@ -243,7 +243,7 @@ See the docs at https://docs.victoriametrics.com/vmauth.html .
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -200,7 +200,7 @@ See [this article](https://medium.com/@valyala/speeding-up-backups-for-big-time-
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -303,6 +303,13 @@ The shortlist of configuration flags is the following:
``` ```
vmbackupmanager performs regular backups according to the provided configs. vmbackupmanager performs regular backups according to the provided configs.
subcommands:
backup: provides auxiliary backup-related commands
restore: restores backup specified by restore mark if it exists
command-line flags:
-apiURL string
vmbackupmanager address to perform API requests (default "http://127.0.0.1:8300")
-concurrency int -concurrency int
The number of concurrent workers. Higher concurrency may reduce backup duration (default 10) The number of concurrent workers. Higher concurrency may reduce backup duration (default 10)
-configFilePath string -configFilePath string
@ -332,7 +339,7 @@ vmbackupmanager performs regular backups according to the provided configs.
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap
@ -396,8 +403,6 @@ vmbackupmanager performs regular backups according to the provided configs.
-pushmetrics.url array -pushmetrics.url array
Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage Optional URL to push metrics exposed at /metrics page. See https://docs.victoriametrics.com/#push-metrics . By default metrics exposed at /metrics page aren't pushed to any remote storage
Supports an array of values separated by comma or specified via multiple flags. Supports an array of values separated by comma or specified via multiple flags.
-restoreOnStart
Check if backup restore was requested and restore requested backup.
-runOnStart -runOnStart
Upload backups immediately after start of the service. Otherwise the backup starts on new hour Upload backups immediately after start of the service. Otherwise the backup starts on new hour
-s3ForcePathStyle -s3ForcePathStyle

View file

@ -180,8 +180,8 @@ curl 'http://localhost:8431/api/v1/labels' -H 'Authorization: Bearer eyJhbGciOiJ
The shortlist of configuration flags include the following: The shortlist of configuration flags include the following:
```console ```console
-auth.httpHeader -auth.httpHeader string
HTTP header name to look for JWT authorization token HTTP header name to look for JWT authorization token (default "Authorization")
-clusterMode -clusterMode
enable this for the cluster version enable this for the cluster version
-datasource.appendTypePrefix -datasource.appendTypePrefix
@ -215,7 +215,7 @@ The shortlist of configuration flags include the following:
-datasource.oauth2.tokenUrl string -datasource.oauth2.tokenUrl string
Optional OAuth2 tokenURL to use for -datasource.url. Optional OAuth2 tokenURL to use for -datasource.url.
-datasource.queryStep duration -datasource.queryStep duration
queryStep defines how far a value can fallback to when evaluating queries. For example, if datasource.queryStep=15s then param "step" with value "15s" will be added to every query.If queryStep isn't specified, rule's evaluationInterval will be used instead. How far a value can fallback to when evaluating queries. For example, if -datasource.queryStep=15s then param "step" with value "15s" will be added to every query. If set to 0, rule's evaluation interval will be used instead. (default 5m0s)
-datasource.queryTimeAlignment -datasource.queryTimeAlignment
Whether to align "time" parameter with evaluation interval.Alignment supposed to produce deterministic results despite of number of vmalert replicas or time they were started. See more details here https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1257 (default true) Whether to align "time" parameter with evaluation interval.Alignment supposed to produce deterministic results despite of number of vmalert replicas or time they were started. See more details here https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1257 (default true)
-datasource.roundDigits int -datasource.roundDigits int
@ -245,7 +245,7 @@ The shortlist of configuration flags include the following:
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

View file

@ -104,7 +104,7 @@ i.e. the end result would be similar to [rsync --delete](https://askubuntu.com/q
-envflag.prefix string -envflag.prefix string
Prefix for environment variables if -envflag.enable is set Prefix for environment variables if -envflag.enable is set
-eula -eula
By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in enterprise version of VictoriaMetrics By specifying this flag, you confirm that you have an enterprise license and accept the EULA https://victoriametrics.com/assets/VM_EULA.pdf . This flag is available only in VictoriaMetrics enterprise. See https://docs.victoriametrics.com/enterprise.html
-flagsAuthKey string -flagsAuthKey string
Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings Auth key for /flags endpoint. It must be passed via authKey query arg. It overrides httpAuth.* settings
-fs.disableMmap -fs.disableMmap

20
go.mod
View file

@ -12,11 +12,11 @@ require (
// like https://github.com/valyala/fasthttp/commit/996610f021ff45fdc98c2ce7884d5fa4e7f9199b // like https://github.com/valyala/fasthttp/commit/996610f021ff45fdc98c2ce7884d5fa4e7f9199b
github.com/VictoriaMetrics/fasthttp v1.1.0 github.com/VictoriaMetrics/fasthttp v1.1.0
github.com/VictoriaMetrics/metrics v1.23.0 github.com/VictoriaMetrics/metrics v1.23.0
github.com/VictoriaMetrics/metricsql v0.47.0 github.com/VictoriaMetrics/metricsql v0.49.0
github.com/aws/aws-sdk-go-v2 v1.17.1 github.com/aws/aws-sdk-go-v2 v1.17.1
github.com/aws/aws-sdk-go-v2/config v1.17.10 github.com/aws/aws-sdk-go-v2/config v1.18.3
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.42
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1 github.com/aws/aws-sdk-go-v2/service/s3 v1.29.4
github.com/cespare/xxhash/v2 v2.1.2 github.com/cespare/xxhash/v2 v2.1.2
github.com/cheggaaa/pb/v3 v3.1.0 github.com/cheggaaa/pb/v3 v3.1.0
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
@ -45,14 +45,14 @@ require (
) )
require ( require (
cloud.google.com/go v0.106.0 // indirect cloud.google.com/go v0.107.0 // indirect
cloud.google.com/go/compute v1.12.1 // indirect cloud.google.com/go/compute v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go/iam v0.7.0 // indirect cloud.google.com/go/iam v0.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.12.23 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.3 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 // indirect
@ -64,7 +64,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.17.5 // indirect
github.com/aws/smithy-go v1.13.4 // indirect github.com/aws/smithy-go v1.13.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/go-kit/log v0.2.1 // indirect github.com/go-kit/log v0.2.1 // indirect
@ -81,7 +81,7 @@ require (
github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect
github.com/rivo/uniseg v0.4.2 // indirect github.com/rivo/uniseg v0.4.3 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/histogram v1.2.0 // indirect github.com/valyala/histogram v1.2.0 // indirect
@ -93,7 +93,7 @@ require (
golang.org/x/text v0.4.0 // indirect golang.org/x/text v0.4.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66 // indirect google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect
google.golang.org/grpc v1.50.1 // indirect google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
) )

40
go.sum
View file

@ -15,8 +15,8 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.106.0 h1:AWaMWuZb2oFeiV91OfNHZbmwUhMVuXEaLPm9sqDAOl8= cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww=
cloud.google.com/go v0.106.0/go.mod h1:5NEGxGuIeMQiPaWLwLYZ7kfNWiP6w1+QJK+xqyIT+dw= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -100,8 +100,8 @@ github.com/VictoriaMetrics/fasthttp v1.1.0/go.mod h1:/7DMcogqd+aaD3G3Hg5kFgoFwlR
github.com/VictoriaMetrics/metrics v1.18.1/go.mod h1:ArjwVz7WpgpegX/JpB0zpNF2h2232kErkEnzH1sxMmA= github.com/VictoriaMetrics/metrics v1.18.1/go.mod h1:ArjwVz7WpgpegX/JpB0zpNF2h2232kErkEnzH1sxMmA=
github.com/VictoriaMetrics/metrics v1.23.0 h1:WzfqyzCaxUZip+OBbg1+lV33WChDSu4ssYII3nxtpeA= github.com/VictoriaMetrics/metrics v1.23.0 h1:WzfqyzCaxUZip+OBbg1+lV33WChDSu4ssYII3nxtpeA=
github.com/VictoriaMetrics/metrics v1.23.0/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc= github.com/VictoriaMetrics/metrics v1.23.0/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc=
github.com/VictoriaMetrics/metricsql v0.47.0 h1:PQwadjoQnKKkaUiupkDq0ZbCAHX2qP8OOexJ9oJwupo= github.com/VictoriaMetrics/metricsql v0.49.0 h1:7R04eab3gU0PKu8Ksak7SJnORXm0K+hSGt2+t3XGyKg=
github.com/VictoriaMetrics/metricsql v0.47.0/go.mod h1:6pP1ZeLVJHqJrHlF6Ij3gmpQIznSsgktEcZgsAWYel0= github.com/VictoriaMetrics/metricsql v0.49.0/go.mod h1:6pP1ZeLVJHqJrHlF6Ij3gmpQIznSsgktEcZgsAWYel0=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
@ -143,14 +143,14 @@ github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehC
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw= github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 h1:RKci2D7tMwpvGpDNZnGQw9wk6v7o/xSwFcUAuNPoB8k= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 h1:RKci2D7tMwpvGpDNZnGQw9wk6v7o/xSwFcUAuNPoB8k=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9/go.mod h1:vCmV1q1VK8eoQJ5+aYE7PkK1K6v41qJ5pJdK3ggCDvg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9/go.mod h1:vCmV1q1VK8eoQJ5+aYE7PkK1K6v41qJ5pJdK3ggCDvg=
github.com/aws/aws-sdk-go-v2/config v1.17.10 h1:zBy5QQ/mkvHElM1rygHPAzuH+sl8nsdSaxSWj0+rpdE= github.com/aws/aws-sdk-go-v2/config v1.18.3 h1:3kfBKcX3votFX84dm00U8RGA1sCCh3eRMOGzg5dCWfU=
github.com/aws/aws-sdk-go-v2/config v1.17.10/go.mod h1:/4np+UiJJKpWHN7Q+LZvqXYgyjgeXm5+lLfDI6TPZao= github.com/aws/aws-sdk-go-v2/config v1.18.3/go.mod h1:BYdrbeCse3ZnOD5+2/VE/nATOK8fEUpBtmPMdKSyhMU=
github.com/aws/aws-sdk-go-v2/credentials v1.12.23 h1:LctvcJMIb8pxvk5hQhChpCu0WlU6oKQmcYb1HA4IZSA= github.com/aws/aws-sdk-go-v2/credentials v1.13.3 h1:ur+FHdp4NbVIv/49bUjBW+FE7e57HOo03ELodttmagk=
github.com/aws/aws-sdk-go-v2/credentials v1.12.23/go.mod h1:0awX9iRr/+UO7OwRQFpV1hNtXxOVuehpjVEzrIAYNcA= github.com/aws/aws-sdk-go-v2/credentials v1.13.3/go.mod h1:/rOMmqYBcFfNbRPU0iN9IgGqD5+V2yp3iWNmIlz0wI4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37 h1:e1VtTBo+cLNjres0wTlMkmwCGGRjDEkkrz3frxxcaCs= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.42 h1:bxgBYvvBh+W1RnNYP4ROXEB8N+HSSucDszfE7Rb+kfU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37/go.mod h1:kdAV1UMnCkyG6tZJUC4mHbPoRjPA3dIK0L8mnsHERiM= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.42/go.mod h1:LHOsygMiW/14CkFxdXxvzKyMh3jbk/QfZVaDtCbLkl8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 h1:nBO/RFxeq/IS5G9Of+ZrgucRciie2qpLy++3UGZ+q2E= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 h1:nBO/RFxeq/IS5G9Of+ZrgucRciie2qpLy++3UGZ+q2E=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42vVYQY6pvSyJCJcFHlPIiY+YKdPtwnvMkY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42vVYQY6pvSyJCJcFHlPIiY+YKdPtwnvMkY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 h1:oRHDrwCTVT8ZXi4sr9Ld+EXk7N/KGssOr2ygNeojEhw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 h1:oRHDrwCTVT8ZXi4sr9Ld+EXk7N/KGssOr2ygNeojEhw=
@ -167,14 +167,14 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 h1:GE25AWCdN
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19/go.mod h1:02CP6iuYP+IVnBX5HULVdSAku/85eHB2Y9EsFhrkEwU= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19/go.mod h1:02CP6iuYP+IVnBX5HULVdSAku/85eHB2Y9EsFhrkEwU=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 h1:piDBAaWkaxkkVV3xJJbTehXCZRXYs49kvpi/LG6LR2o= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 h1:piDBAaWkaxkkVV3xJJbTehXCZRXYs49kvpi/LG6LR2o=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19/go.mod h1:BmQWRVkLTmyNzYPFAZgon53qKLWBNSvonugD1MrSWUs= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19/go.mod h1:BmQWRVkLTmyNzYPFAZgon53qKLWBNSvonugD1MrSWUs=
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1 h1:/EMdFPW/Ppieh0WUtQf1+qCGNLdsq5UWUyevBQ6vMVc= github.com/aws/aws-sdk-go-v2/service/s3 v1.29.4 h1:QgmmWifaYZZcpaw3y1+ccRlgH6jAvLm4K/MBGUc7cNM=
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1/go.mod h1:/NHbqPRiwxSPVOB2Xr+StDEH+GWV/64WwnUjv4KYzV0= github.com/aws/aws-sdk-go-v2/service/s3 v1.29.4/go.mod h1:/NHbqPRiwxSPVOB2Xr+StDEH+GWV/64WwnUjv4KYzV0=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWqkUDDB3Eje6z3kbG0= github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWqkUDDB3Eje6z3kbG0=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI= github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI=
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1 h1:KRAix/KHvjGODaHAMXnxRk9t0D+4IJVUuS/uwXxngXk= github.com/aws/aws-sdk-go-v2/service/sts v1.17.5 h1:60SJ4lhvn///8ygCzYy2l53bFW/Q15bVfyjyAWo6zuw=
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4= github.com/aws/aws-sdk-go-v2/service/sts v1.17.5/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk= github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk=
github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -766,8 +766,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -1256,8 +1256,8 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/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-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66 h1:wx7sJ5GRBQLRcslTNcrTklsHhHevQvxgztW18txbbZM= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@ -1278,8 +1278,8 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

View file

@ -58,7 +58,9 @@ func newAPIConfig(sdc *SDConfig) (*apiConfig, error) {
logger.Infof("autodetected the current GCE zone: %q", zone) logger.Infof("autodetected the current GCE zone: %q", zone)
} else if len(zones) == 1 && zones[0] == "*" { } else if len(zones) == 1 && zones[0] == "*" {
// Autodetect zones for project. // Autodetect zones for project.
zs, err := getZonesForProject(client, project, sdc.Filter) // Do not pass sdc.Filter when discovering zones, since GCE doesn't support it.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3202
zs, err := getZonesForProject(client, project)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot obtain zones for project %q: %w", project, err) return nil, fmt.Errorf("cannot obtain zones for project %q: %w", project, err)
} }

View file

@ -6,13 +6,13 @@ import (
"net/http" "net/http"
) )
func getZonesForProject(client *http.Client, project, filter string) ([]string, error) { func getZonesForProject(client *http.Client, project string) ([]string, error) {
// See https://cloud.google.com/compute/docs/reference/rest/v1/zones // See https://cloud.google.com/compute/docs/reference/rest/v1/zones
zonesURL := fmt.Sprintf("https://compute.googleapis.com/compute/v1/projects/%s/zones", project) zonesURL := fmt.Sprintf("https://compute.googleapis.com/compute/v1/projects/%s/zones", project)
var zones []string var zones []string
pageToken := "" pageToken := ""
for { for {
data, err := getAPIResponse(client, zonesURL, filter, pageToken) data, err := getAPIResponse(client, zonesURL, "", pageToken)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot obtain zones: %w", err) return nil, fmt.Errorf("cannot obtain zones: %w", err)
} }

Some files were not shown because too many files have changed in this diff Show more