mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-07-14 12:50:23 +03:00
Compare commits
3 Commits
feature/en
...
docs-artic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37056ed0b2 | ||
|
|
8952c5b290 | ||
|
|
9c1ea5d5ad |
@@ -462,9 +462,7 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||
return true
|
||||
case "/prometheus/metric-relabel-debug", "/metric-relabel-debug":
|
||||
promscrapeMetricRelabelDebugRequests.Inc()
|
||||
rwGlobalRelabelConfigs := remotewrite.GetRemoteWriteRelabelConfigString()
|
||||
rwURLRelabelConfigss := remotewrite.GetURLRelabelConfigString()
|
||||
promscrape.WriteMetricRelabelDebug(w, r, rwGlobalRelabelConfigs, rwURLRelabelConfigss)
|
||||
promscrape.WriteMetricRelabelDebug(w, r)
|
||||
return true
|
||||
case "/prometheus/target-relabel-debug", "/target-relabel-debug":
|
||||
promscrapeTargetRelabelDebugRequests.Inc()
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
@@ -83,16 +82,6 @@ func WriteRelabelConfigData(w io.Writer) {
|
||||
_, _ = w.Write(*p)
|
||||
}
|
||||
|
||||
// GetRemoteWriteRelabelConfigString returns -remoteWrite.relabelConfig contents in string
|
||||
func GetRemoteWriteRelabelConfigString() string {
|
||||
var bb bytesutil.ByteBuffer
|
||||
WriteRelabelConfigData(&bb)
|
||||
if bb.Len() == 0 {
|
||||
return ""
|
||||
}
|
||||
return string(bb.B)
|
||||
}
|
||||
|
||||
// WriteURLRelabelConfigData writes -remoteWrite.urlRelabelConfig contents to w
|
||||
func WriteURLRelabelConfigData(w io.Writer) {
|
||||
p := remoteWriteURLRelabelConfigData.Load()
|
||||
@@ -119,24 +108,6 @@ func WriteURLRelabelConfigData(w io.Writer) {
|
||||
_, _ = w.Write(d)
|
||||
}
|
||||
|
||||
// GetURLRelabelConfigString returns -remoteWrite.urlRelabelConfig contents in []string
|
||||
func GetURLRelabelConfigString() []string {
|
||||
p := remoteWriteURLRelabelConfigData.Load()
|
||||
if p == nil {
|
||||
return nil
|
||||
}
|
||||
var ss []string
|
||||
for i := range *remoteWriteURLs {
|
||||
cfgData := (*p)[i]
|
||||
var cfgDataBytes []byte
|
||||
if cfgData != nil {
|
||||
cfgDataBytes, _ = yaml.Marshal(cfgData)
|
||||
}
|
||||
ss = append(ss, string(cfgDataBytes))
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
func reloadRelabelConfigs() {
|
||||
rcs := allRelabelConfigs.Load()
|
||||
if !rcs.isSet() {
|
||||
|
||||
@@ -541,7 +541,7 @@ func handleStaticAndSimpleRequests(w http.ResponseWriter, r *http.Request, path
|
||||
return true
|
||||
case "/metric-relabel-debug":
|
||||
promscrapeMetricRelabelDebugRequests.Inc()
|
||||
promscrape.WriteMetricRelabelDebug(w, r, "", nil)
|
||||
promscrape.WriteMetricRelabelDebug(w, r)
|
||||
return true
|
||||
case "/target-relabel-debug":
|
||||
promscrapeTargetRelabelDebugRequests.Inc()
|
||||
|
||||
@@ -154,6 +154,13 @@ See [our blog](https://victoriametrics.com/blog) for the latest articles written
|
||||
* [Why irate from Prometheus doesn't capture spikes](https://valyala.medium.com/why-irate-from-prometheus-doesnt-capture-spikes-45f9896d7832)
|
||||
* [VictoriaMetrics: PromQL compliance](https://medium.com/@romanhavronenko/victoriametrics-promql-compliance-d4318203f51e)
|
||||
* [How do open source solutions for logs work: Elasticsearch, Loki and VictoriaLogs](https://itnext.io/how-do-open-source-solutions-for-logs-work-elasticsearch-loki-and-victorialogs-9f7097ecbc2f)
|
||||
* [How vmagent Collects and Ships Metrics Fast with Aggregation, Deduplication, and More](https://victoriametrics.com/blog/vmagent-how-it-works/)
|
||||
* [When Metrics Meet vminsert: A Data-Delivery Story](https://victoriametrics.com/blog/vminsert-how-it-works/)
|
||||
* [How vmstorage Handles Data Ingestion From vminsert](https://victoriametrics.com/blog/vmstorage-how-it-handles-data-ingestion/)
|
||||
* [How vmstorage Processes Data: Retention, Merging, Deduplication,...](https://victoriametrics.com/blog/vmstorage-retention-merging-deduplication/)
|
||||
* [How vmstorage's IndexDB Works](https://victoriametrics.com/blog/vmstorage-how-indexdb-works/)
|
||||
* [How vmstorage Handles Query Requests From vmselect](https://victoriametrics.com/blog/vmstorage-how-it-handles-query-requests/)
|
||||
* [Inside vmselect: The Query Processing Engine of VictoriaMetrics](https://victoriametrics.com/blog/vmselect-how-it-works/)
|
||||
|
||||
### Tutorials, guides and how-to articles
|
||||
|
||||
@@ -171,6 +178,12 @@ See [our guides](https://docs.victoriametrics.com/guides/) for the up-to-date gu
|
||||
* [Prometheus storage: tech terms for humans](https://valyala.medium.com/prometheus-storage-technical-terms-for-humans-4ab4de6c3d48)
|
||||
* [Cardinality explorer](https://victoriametrics.com/blog/cardinality-explorer/)
|
||||
* [Rules backfilling via vmalert](https://victoriametrics.com/blog/rules-replay/)
|
||||
* [vmagent: Key Features Explained in Under 15 Minutes](https://victoriametrics.com/blog/vmagent-key-features-explained/)
|
||||
* [Prometheus Metrics Explained: Counters, Gauges, Histograms & Summaries](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/)
|
||||
* [Prometheus Monitoring: Instant Queries and Range Queries Explained](https://victoriametrics.com/blog/prometheus-monitoring-instant-range-query/)
|
||||
* [Prometheus Monitoring: Functions, Subqueries, Operators, and Modifiers](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/)
|
||||
* [Prometheus Alerting 101: Rules, Recording Rules, and Alertmanager](https://victoriametrics.com/blog/alerting-recording-rules-alertmanager/)
|
||||
* [Alerting Best Practices](https://victoriametrics.com/blog/alerting-best-practices/)
|
||||
|
||||
### Other articles
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ Each service may scale independently and may run on the most suitable hardware.
|
||||
This is a [shared nothing architecture](https://en.wikipedia.org/wiki/Shared-nothing_architecture).
|
||||
It increases cluster availability, and simplifies cluster maintenance as well as cluster scaling.
|
||||
|
||||
> Further reading, deep dives into how each service works internally:
|
||||
> - `vmstorage`: [How vmstorage Handles Data Ingestion From vminsert](https://victoriametrics.com/blog/vmstorage-how-it-handles-data-ingestion/), [How vmstorage's IndexDB Works](https://victoriametrics.com/blog/vmstorage-how-indexdb-works/), [How vmstorage Handles Query Requests From vmselect](https://victoriametrics.com/blog/vmstorage-how-it-handles-query-requests/).
|
||||
> - `vmselect`: [Inside vmselect: The Query Processing Engine of VictoriaMetrics](https://victoriametrics.com/blog/vmselect-how-it-works/).
|
||||
|
||||

|
||||
|
||||
## vmui
|
||||
@@ -834,7 +838,7 @@ This ensures that incoming metrics are evenly distributed across all `vmstorage`
|
||||
The downside is that a single slow vmstorage node can throttle the entire cluster.
|
||||
|
||||
When `-disableRerouting=false` is enabled on `vminsert`,
|
||||
the cluster will automatically re-route writes away from the slowest vmstorage node to preserve maximum ingestion throughput.
|
||||
the cluster will automatically [re-route writes](https://victoriametrics.com/blog/vminsert-how-it-works/#31-rerouting) away from the slowest vmstorage node to preserve maximum ingestion throughput.
|
||||
|
||||
Re-routing occurs only when all of the following conditions hold:
|
||||
- the storage send buffer is full.
|
||||
@@ -877,7 +881,7 @@ See also [resource usage limits docs](#resource-usage-limits).
|
||||
|
||||
## Rebalancing
|
||||
|
||||
Every `vminsert` node evenly spreads (shards) incoming data among `vmstorage` nodes specified in the `-storageNode` command-line flag.
|
||||
Every `vminsert` node [evenly spreads (shards) incoming data](https://victoriametrics.com/blog/vminsert-how-it-works/#3-sharding-and-buffering) among `vmstorage` nodes specified in the `-storageNode` command-line flag.
|
||||
This guarantees even distribution of the ingested data among `vmstorage` nodes. When new `vmstorage` nodes are added to the `-storageNode`
|
||||
command-line flag at `vminsert`, then only newly ingested data is distributed evenly among old and new `vmstorage` nodes, while
|
||||
historical data remains on the old `vmstorage` nodes. This speeds up data ingestion and querying for the majority of production workloads,
|
||||
@@ -1025,7 +1029,7 @@ By default, VictoriaMetrics offloads replication to the underlying storage point
|
||||
which guarantees data durability. VictoriaMetrics supports application-level replication if replicated durable persistent disks cannot be used for some reason.
|
||||
|
||||
The replication can be enabled by passing `-replicationFactor=N` command-line flag to `vminsert`. This instructs `vminsert` to store `N` copies for every ingested sample
|
||||
on `N` distinct `vmstorage` nodes. This guarantees that all the stored data remains available for querying if up to `N-1` `vmstorage` nodes are unavailable.
|
||||
on `N` distinct `vmstorage` nodes. This guarantees that all the stored data remains available for querying if up to `N-1` `vmstorage` nodes are unavailable. See [how `vminsert` replicates each sample to `N` `vmstorage` nodes](https://victoriametrics.com/blog/vminsert-how-it-works/#4-replication-and-sending-data-to-vmstorage) for details.
|
||||
|
||||
Passing `-replicationFactor=N` command-line flag to `vmselect` instructs it to not mark responses as `partial` if less than `-replicationFactor` vmstorage nodes are unavailable during the query.
|
||||
See [cluster availability docs](#cluster-availability) for details.
|
||||
@@ -1060,7 +1064,7 @@ deduplication can't be guaranteed when samples and sample duplicates for the sam
|
||||
- when `vmstorage` node has no enough capacity for processing incoming data stream. Then `vminsert` re-routes new samples to other `vmstorage` nodes.
|
||||
|
||||
It is recommended to set **the same** `-dedup.minScrapeInterval` command-line flag value to both `vmselect` and `vmstorage` nodes
|
||||
to ensure query results consistency, even if storage layer didn't complete deduplication yet.
|
||||
to ensure query results consistency, even if [storage layer didn't complete deduplication](https://victoriametrics.com/blog/vmstorage-retention-merging-deduplication/#deduplication) yet.
|
||||
|
||||
## Metrics Metadata
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ Other PromQL functionality should work the same in MetricsQL.
|
||||
|
||||
MetricsQL implements [PromQL](https://medium.com/@valyala/promql-tutorial-for-beginners-9ab455142085)
|
||||
and provides additional functionality mentioned below, which is aimed towards solving practical cases.
|
||||
See [operators and modifiers in MetricsQL](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/#operators--modifiers) for details.
|
||||
Feel free [filing a feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues) if you think MetricsQL misses certain useful functionality.
|
||||
|
||||
This functionality can be evaluated at [VictoriaMetrics demo playground](https://play.victoriametrics.com/select/accounting/1/6a716b0f-38bc-4856-90ce-448fd713e3fe/prometheus/graph/)
|
||||
@@ -156,7 +157,7 @@ MetricsQL provides the following functions:
|
||||
|
||||
### Rollup functions
|
||||
|
||||
**Rollup functions** (aka range functions or window functions) calculate rollups over [raw samples](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#raw-samples)
|
||||
**[Rollup functions](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/#rollup-functions)** (aka range functions or window functions) calculate rollups over [raw samples](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#raw-samples)
|
||||
on the given lookbehind window for the [selected time series](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#filtering).
|
||||
For example, `avg_over_time(temperature[24h])` calculates the average temperature over [raw samples](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#raw-samples) for the last 24 hours.
|
||||
|
||||
@@ -348,6 +349,7 @@ If the lookbehind window is skipped in square brackets, then it is automatically
|
||||
passed to [/api/v1/query_range](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#range-query) or [/api/v1/query](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#instant-query),
|
||||
while `scrape_interval` is the interval between [raw samples](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#raw-samples) for the selected time series.
|
||||
This allows avoiding unexpected gaps on the graph when `step` is smaller than the `scrape_interval`.
|
||||
See [range vector selectors](https://victoriametrics.com/blog/prometheus-monitoring-instant-range-query/#range-vector-selector) for details.
|
||||
|
||||
#### delta
|
||||
|
||||
@@ -1110,7 +1112,7 @@ See also [zscore](#zscore), [range_trim_zscore](#range_trim_zscore) and [outlier
|
||||
|
||||
### Transform functions
|
||||
|
||||
**Transform functions** calculate transformations over [rollup results](#rollup-functions).
|
||||
**[Transform functions](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/#transformation-functions)** calculate transformations over [rollup results](#rollup-functions).
|
||||
For example, `abs(delta(temperature[24h]))` calculates the absolute value for every point of every time series
|
||||
returned from the rollup `delta(temperature[24h])`.
|
||||
|
||||
@@ -1846,7 +1848,7 @@ This function is supported by PromQL.
|
||||
|
||||
### Label manipulation functions
|
||||
|
||||
**Label manipulation functions** perform manipulations with labels on the selected [rollup results](#rollup-functions).
|
||||
**[Label manipulation functions](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/#label-manipulation-functions)** perform manipulations with labels on the selected [rollup results](#rollup-functions).
|
||||
|
||||
Additional details:
|
||||
|
||||
@@ -2016,7 +2018,7 @@ See also [sort_by_label_numeric](#sort_by_label_numeric) and [sort_by_label_desc
|
||||
|
||||
### Aggregate functions
|
||||
|
||||
**Aggregate functions** calculate aggregates over groups of [rollup results](#rollup-functions).
|
||||
**[Aggregate functions](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/#aggregation-functions)** calculate aggregates over groups of [rollup results](#rollup-functions).
|
||||
|
||||
Additional details:
|
||||
|
||||
@@ -2339,7 +2341,7 @@ See also [zscore_over_time](#zscore_over_time), [range_trim_zscore](#range_trim_
|
||||
|
||||
## Subqueries
|
||||
|
||||
MetricsQL supports and extends PromQL subqueries. See [this article](https://valyala.medium.com/prometheus-subqueries-in-victoriametrics-9b1492b720b3) for details.
|
||||
MetricsQL supports and extends PromQL [subqueries](https://victoriametrics.com/blog/prometheus-monitoring-function-operator-modifier/#subqueries). See [this article](https://valyala.medium.com/prometheus-subqueries-in-victoriametrics-9b1492b720b3) for details.
|
||||
Any [rollup function](#rollup-functions) for something other than [series selector](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#filtering) form a subquery.
|
||||
Nested rollup functions can be implicit thanks to the [implicit query conversions](#implicit-query-conversions).
|
||||
For example, `delta(sum(m))` is implicitly converted to `delta(sum(default_rollup(m))[1i:1i])`, so it becomes a subquery,
|
||||
|
||||
@@ -1314,6 +1314,7 @@ per each `-dedup.minScrapeInterval` discrete interval if `-dedup.minScrapeInterv
|
||||
For example, `-dedup.minScrapeInterval=60s` would leave a single raw sample with the biggest timestamp per each discrete
|
||||
`60s` interval.
|
||||
This aligns with the [staleness rules in Prometheus](https://prometheus.io/docs/prometheus/latest/querying/basics/#staleness).
|
||||
See [how deduplication works](https://victoriametrics.com/blog/vmstorage-retention-merging-deduplication/#deduplication) for details.
|
||||
|
||||
If multiple raw samples have **the same timestamp** on the given `-dedup.minScrapeInterval` discrete interval,
|
||||
then the sample with **the biggest value** is kept.
|
||||
@@ -1397,7 +1398,7 @@ in separate files under `part` directory - `timestamps.bin` and `values.bin`.
|
||||
The `part` directory also contains `index.bin` and `metaindex.bin` files - these files contain index
|
||||
for fast block lookups, which belong to the given `TSID` and cover the given time range.
|
||||
|
||||
`Parts` are periodically merged into bigger parts in background. The background merge provides the following benefits:
|
||||
`Parts` are periodically merged into bigger parts in background. The [background merge](https://victoriametrics.com/blog/vmstorage-retention-merging-deduplication/#merge-process) provides the following benefits:
|
||||
|
||||
* keeping the number of data files under control, so they don't exceed limits on open files
|
||||
* improved data compression, since bigger parts are usually compressed better than smaller parts
|
||||
@@ -1532,6 +1533,7 @@ are **eventually deleted** during [background merge](https://medium.com/@valyala
|
||||
The time range covered by data part is **not limited by retention period unit**. One data part can cover hours or days of
|
||||
data. Hence, a data part can be deleted only **when fully outside the configured retention**.
|
||||
See more about partitions and parts in the [Storage section](#storage).
|
||||
See [how retention frees disk space](https://victoriametrics.com/blog/vmstorage-retention-merging-deduplication/#retention-free-disk-space-guard-and-downsampling) for details.
|
||||
|
||||
The maximum disk space usage for a given `-retentionPeriod` is going to be (`-retentionPeriod` + 1) months.
|
||||
For example, if `-retentionPeriod` is set to 1, data for January is deleted on March 1st.
|
||||
@@ -1634,6 +1636,7 @@ See how to request a [free trial license](https://victoriametrics.com/products/e
|
||||
This command-line flag instructs leaving the last sample per each `interval` for [time series](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#time-series)
|
||||
[samples](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#raw-samples) older than the `offset`. The `offset` must be a multiple of `interval`. For example, `-downsampling.period=30d:5m` instructs leaving the last sample
|
||||
per each 5-minute interval for samples older than 30 days, while the rest of samples are dropped.
|
||||
See [Enterprise downsampling internals](https://victoriametrics.com/blog/vmstorage-retention-merging-deduplication/#retention-filters-and-downsampling-enterprise-plan) for details.
|
||||
|
||||
The `-downsampling.period` command-line flag can be specified multiple times in order to apply different downsampling levels for different time ranges (aka multi-level downsampling).
|
||||
For example, `-downsampling.period=30d:5m,180d:1h` instructs leaving the last sample per each 5-minute interval for samples older than 30 days,
|
||||
|
||||
@@ -25,19 +25,18 @@ The sandbox cluster installation runs under the constant load generated by
|
||||
See also [LTS releases](https://docs.victoriametrics.com/victoriametrics/lts-releases/).
|
||||
|
||||
## tip
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/): flush pending persistent queue data to chunk file before updating the metadata. This prevents the metadata writer offset from getting ahead of the chunk file size and avoids losing the persistent queue after an unclean shutdown. See [#11192](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11192).
|
||||
|
||||
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/victoriametrics/metricsql/): support `fill` modifiers to allow missing series on either side of a binary operation to be filled with a provided default value. See [#10598](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10598).
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/) and [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/): Improve background discovery performance for [http_sd](https://docs.victoriametrics.com/victoriametrics/sd_configs/#http_sd_configs) discovery. See [#8838](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8838).
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/) and [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/): allow overriding `max_scrape_size` on a per-target basis via the `__max_scrape_size__` label during target relabeling. See [#11188](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11188).
|
||||
* FEATURE: [vmstorage](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/) and [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/): add `-maxBackfillAge` command-line flag for limiting ingestion of samples with historical timestamps, for example, when older data has been moved between storage tiers (nvme/hdd, hot/cold). See [#11199](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11199). Thanks to @AshwinRamaniPsg for contribution.
|
||||
* FEATURE: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/): add support for selecting relabel configurations from `-remoteWrite.relabelConfig` and `-remoteWrite.urlRelabelConfig` in the [metrics relabel debug UI](https://docs.victoriametrics.com/victoriametrics/relabeling/#relabel-debugging). See [#9918](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9918).
|
||||
|
||||
* BUGFIX: `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): Now drops metadata blocks when communicating with vmstorage nodes over the legacy RPC protocol. To avoid this limitation, upgrade `vmstorage` to a version that supports the new RPC protocol (>= [v1.137.0](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/docs/victoriametrics/changelog/CHANGELOG.md#v11370)). See [#11146](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11146).
|
||||
* BUGFIX: [vmbackup](https://docs.victoriametrics.com/victoriametrics/vmbackup/) and [vmbackupmanager](https://docs.victoriametrics.com/victoriametrics/vmbackupmanager/): retry S3 requests failing with `HTTP 429` status code or `TooManyRequests` error code. Previously such requests were not retried, so a short burst of rate limiting would fail the whole backup. See [#11218](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11218). Thanks to @gautamrizwani for contribution.
|
||||
* BUGFIX: `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): properly apply limit to metrics metadata response. See [#11139](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11139).
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): keep only one header navigation dropdown (`Explore`, `Tools`) open at a time. Previously, hovering across two dropdowns could briefly leave both open due to the close delay. See [#11224](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11224). Thanks to @antedotee for contribution.
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/): fix a possible data race when processing OpenTelemetry metadata. See [#11238](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11238). Thanks to @nevgeny for contribution.
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/): flush pending persistent queue data to chunk file before updating the metadata. This prevents the metadata writer offset from getting ahead of the chunk file size and avoids losing the persistent queue after an unclean shutdown. See [#11192](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11192).
|
||||
|
||||
## [v1.147.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.147.0)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ requests_total{path="/", code="403"}
|
||||
The meta-information - a set of `labels` in curly braces - gives us a context for which `path` and with what `code`
|
||||
the `request` was served. Label-value pairs are always of a `string` type. VictoriaMetrics data model is schemaless,
|
||||
which means there is no need to define metric names or their labels in advance. The user is free to add or change ingested
|
||||
metrics anytime.
|
||||
metrics anytime. See [metric names and labels explained](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/#metric-name-and-labels) for details.
|
||||
|
||||
Actually, the metric name is also a label with a special name `__name__`.
|
||||
The `__name__` key could be omitted {{% available_from "v1.111.0" %}} for simplicity. So the following series are identical:
|
||||
@@ -75,7 +75,7 @@ See [these docs](https://docs.victoriametrics.com/victoriametrics/faq/#what-is-h
|
||||
|
||||
#### Raw samples
|
||||
|
||||
Every unique time series may consist of an arbitrary number of `(value, timestamp)` data points (aka `raw samples`) sorted by `timestamp`.
|
||||
Every unique time series may consist of an arbitrary number of `(value, timestamp)` data points (aka [`raw samples`](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/#sample)) sorted by `timestamp`.
|
||||
VictoriaMetrics stores all the `values` as [float64](https://en.wikipedia.org/wiki/Double-precision_floating-point_format)
|
||||
with [extra compression](https://faun.pub/victoriametrics-achieving-better-compression-for-time-series-data-than-gorilla-317bc1f95932) applied.
|
||||
This allows storing precise integer values with up to 12 decimal digits and any floating-point values with up to 12 significant decimal digits.
|
||||
@@ -126,7 +126,7 @@ type exists specifically to help users to understand how the metric was measured
|
||||
|
||||
#### Counter
|
||||
|
||||
Counter is a metric, which counts some events. Its value increases or stays the same over time.
|
||||
[Counter](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/#counter) is a metric, which counts some events. Its value increases or stays the same over time.
|
||||
It cannot decrease in general case. The only exception is e.g. `counter reset`,
|
||||
when the metric resets to zero. The `counter reset` can occur when the service, which exposes the counter, restarts.
|
||||
So, the `counter` metric shows the number of observed events since the service start.
|
||||
@@ -157,7 +157,7 @@ by humans from other metric types.
|
||||
|
||||
#### Gauge
|
||||
|
||||
Gauge is used for measuring a value that can go up and down:
|
||||
[Gauge](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/#gauge) is used for measuring a value that can go up and down:
|
||||
|
||||

|
||||
|
||||
@@ -178,7 +178,7 @@ and [rollup functions](https://docs.victoriametrics.com/victoriametrics/metricsq
|
||||
|
||||
#### Histogram
|
||||
|
||||
Histogram is a set of [counter](#counter) metrics with different `vmrange` or `le` labels.
|
||||
[Histogram](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/#histogram) is a set of [counter](#counter) metrics with different `vmrange` or `le` labels.
|
||||
The `vmrange` or `le` labels define measurement boundaries of a particular bucket.
|
||||
When the observed measurement hits a particular bucket, then the corresponding counter is incremented.
|
||||
|
||||
@@ -282,7 +282,7 @@ We recommend reading the following articles before you start using histograms:
|
||||
|
||||
#### Summary
|
||||
|
||||
Summary metric type is quite similar to [histogram](#histogram) and is used for
|
||||
[Summary](https://victoriametrics.com/blog/prometheus-monitoring-metrics-counters-gauges-histogram-summaries/#summary) metric type is quite similar to [histogram](#histogram) and is used for
|
||||
[quantiles](https://prometheus.io/docs/practices/histograms/#quantiles) calculations. The main difference
|
||||
is that calculations are made on the client-side, so metrics exposition format already contains pre-defined
|
||||
quantiles:
|
||||
@@ -504,6 +504,7 @@ Params:
|
||||
The result of Instant query is a list of [time series](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#time-series)
|
||||
matching the filter in `query` expression. Each returned series contains exactly one `(timestamp, value)` entry,
|
||||
where `timestamp` equals to the `time` query arg, while the `value` contains `query` result at the requested `time`.
|
||||
See [instant vectors explained](https://victoriametrics.com/blog/prometheus-monitoring-instant-range-query/#instant-vector) for details.
|
||||
|
||||
To understand how instant queries work, let's begin with a data sample:
|
||||
|
||||
@@ -606,6 +607,7 @@ at `start`, `start+step`, `start+2*step`, ..., `start+N*step` timestamps. In oth
|
||||
executed independently at `start`, `start+step`, ..., `start+N*step` timestamps with the only difference that an instant query
|
||||
does not return `ephemeral` samples (see below). Instead, if the database does not contain any samples for the requested time and step,
|
||||
it simply returns an empty result.
|
||||
See [range vectors explained](https://victoriametrics.com/blog/prometheus-monitoring-instant-range-query/#range-vector) for details.
|
||||
|
||||
|
||||
For example, to get the values of `foo_bar` during the time range from `2022-05-10T07:59:00Z` to `2022-05-10T08:17:00Z`,
|
||||
|
||||
@@ -127,7 +127,8 @@ See [these docs](#how-to-collect-metrics-in-prometheus-format) for details.
|
||||
|
||||
`vmagent` can be used as an alternative to [StatsD](https://github.com/statsd/statsd)
|
||||
when [stream aggregation](https://docs.victoriametrics.com/victoriametrics/stream-aggregation/) is enabled.
|
||||
See [these docs](https://docs.victoriametrics.com/victoriametrics/stream-aggregation/#statsd-alternative) for details.
|
||||
See [these docs](https://docs.victoriametrics.com/victoriametrics/stream-aggregation/#statsd-alternative) for details,
|
||||
or the blog post on [how vmagent's stream aggregation works](https://victoriametrics.com/blog/vmagent-key-features-explained/#stream-aggregation).
|
||||
|
||||
### Flexible metrics relay
|
||||
|
||||
@@ -137,7 +138,7 @@ to other remote storage systems that support Prometheus `remote_write` protocol
|
||||
|
||||
### Replication and high availability
|
||||
|
||||
`vmagent` replicates the collected metrics among multiple remote storage instances configured via `-remoteWrite.url` args.
|
||||
`vmagent` [replicates the collected metrics](https://victoriametrics.com/blog/vmagent-how-it-works/#step-4-sharding--replication) among multiple remote storage instances configured via `-remoteWrite.url` args.
|
||||
If a single remote storage instance is temporarily unavailable, the collected data remains available on the other remote storage instances.
|
||||
`vmagent` buffers the collected data in files at `-remoteWrite.tmpDataPath` until the remote storage becomes available again.
|
||||
Then it sends the buffered data to the remote storage in order to prevent data gaps.
|
||||
@@ -150,7 +151,8 @@ See [these docs](https://docs.victoriametrics.com/victoriametrics/cluster-victor
|
||||
|
||||
`vmagent` can add, remove, or update labels on the collected data before sending it to the remote storage.
|
||||
It can filter scrape targets or remove unwanted samples via Prometheus-like relabeling.
|
||||
Please see the [Relabeling cookbook](https://docs.victoriametrics.com/victoriametrics/relabeling/) for details.
|
||||
Please see the [Relabeling cookbook](https://docs.victoriametrics.com/victoriametrics/relabeling/) for details,
|
||||
or the blog post on [how vmagent applies global relabeling to reduce cardinality](https://victoriametrics.com/blog/vmagent-how-it-works/#step-2-global-relabeling-cardinality-reduction).
|
||||
|
||||
### Sharding among remote storages
|
||||
|
||||
@@ -158,6 +160,7 @@ By default, `vmagent` replicates data to remote storage systems via the `-remote
|
||||
If the `-remoteWrite.shardByURL` command-line flag is set, then `vmagent` spreads
|
||||
the outgoing [time series](https://docs.victoriametrics.com/victoriametrics/keyconcepts/#time-series) evenly among all the remote storage
|
||||
systems listed in `-remoteWrite.url`.
|
||||
See the blog post on [how vmagent shards data across remote storage systems](https://victoriametrics.com/blog/vmagent-key-features-explained/#sharding) for the details.
|
||||
|
||||
It is possible to replicate samples among remote storage systems by passing `-remoteWrite.shardByURLReplicas=N`
|
||||
to `vmagent` in addition to the `-remoteWrite.shardByURL` command-line flag.
|
||||
@@ -268,7 +271,9 @@ for the collected samples. Examples:
|
||||
```sh
|
||||
./vmagent -remoteWrite.url=http://remote-storage/api/v1/write -streamAggr.dropInputLabels=replica -streamAggr.dedupInterval=60s
|
||||
```
|
||||
|
||||
|
||||
See the blog post on [how vmagent performs global deduplication and stream aggregation](https://victoriametrics.com/blog/vmagent-how-it-works/#step-3-global-deduplication--stream-aggregation) for the details.
|
||||
|
||||
### Monitoring Data eXchange
|
||||
|
||||
The Monitoring Data eXchange (MDX){{% available_from "v1.147.0" %}} feature allows `vmagent` to forward only VictoriaMetrics metrics to selected `-remoteWrite.url` destinations while dropping metrics from non-VictoriaMetrics services.
|
||||
@@ -357,6 +362,8 @@ in addition to the pull-based Prometheus-compatible targets' scraping:
|
||||
* Prometheus exposition format via `http://<vmagent>:8429/api/v1/import/prometheus`. See [these docs](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-import-data-in-prometheus-exposition-format) for details.
|
||||
* Arbitrary CSV data via `http://<vmagent>:8429/api/v1/import/csv`. See [these docs](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-import-csv-data).
|
||||
|
||||
See the blog post on [how vmagent receives data via push APIs or scraping](https://victoriametrics.com/blog/vmagent-how-it-works/#step-1-receiving-data-via-api-or-scrape) for the details.
|
||||
|
||||
## How to collect metrics in Prometheus format
|
||||
|
||||
Specify the path to the `prometheus.yml` file via the `-promscrape.config` command-line flag. `vmagent` takes into account the following
|
||||
@@ -490,15 +497,13 @@ SRV URLs are useful when HTTP services run on different TCP ports or when their
|
||||
|
||||
When comparing the remote protocols between VictoriaMetrics and Prometheus, VictoriaMetrics provides the following benefits:
|
||||
|
||||
* Reduced network bandwidth usage by 2x-5x. This allows saving network bandwidth usage costs when `vmagent` and
|
||||
* Reduced network bandwidth usage by 2x-5x. This allows [saving network bandwidth usage costs](https://victoriametrics.com/blog/victoriametrics-remote-write/) when `vmagent` and
|
||||
the configured remote storage systems are located in different datacenters, availability zones, or regions.
|
||||
|
||||
* Reduced disk read/write IO and disk space usage at `vmagent` when the remote storage is temporarily unavailable.
|
||||
In this case, `vmagent` buffers incoming data to disk using the VictoriaMetrics remote write format.
|
||||
This reduces disk read/write IO and disk space usage by 2x-5x compared to the Prometheus remote write format.
|
||||
|
||||
> See blogpost [Save network costs with VictoriaMetrics remote write protocol](https://victoriametrics.com/blog/victoriametrics-remote-write/).
|
||||
|
||||
`vmagent` uses VictoriaMetrics remote write protocol by default {{% available_from "v1.116.0" %}} when it sends data to VictoriaMetrics components such as other `vmagent` instances,
|
||||
[single-node VictoriaMetrics](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/)
|
||||
or `vminsert` at [cluster version](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/). If needed, it can automatically downgrade to a Prometheus protocol at runtime.
|
||||
@@ -835,7 +840,7 @@ as soon as it is parsed in stream parsing mode.
|
||||
## Scraping big number of targets
|
||||
|
||||
A single `vmagent` instance can scrape tens of thousands of scrape targets. Sometimes this isn't enough due to limitations on CPU, network, RAM, etc.
|
||||
In this case, scrape targets can be split among multiple `vmagent` instances (aka `vmagent` horizontal scaling, sharding, and clustering).
|
||||
In this case, scrape targets can be split among multiple `vmagent` instances (aka [`vmagent` horizontal scaling](https://victoriametrics.com/blog/vmagent-key-features-explained/#scaling-vmagent), sharding, and clustering).
|
||||
The number of `vmagent` instances in the cluster must be passed to the `-promscrape.cluster.membersCount` command-line flag.
|
||||
Each `vmagent` instance in the cluster must use identical `-promscrape.config` files with distinct `-promscrape.cluster.memberNum` values
|
||||
in the range `0 ... N-1`, where `N` is the number of `vmagent` instances in the cluster specified via `-promscrape.cluster.membersCount`.
|
||||
@@ -948,7 +953,7 @@ scrape_configs:
|
||||
|
||||
## On-disk persistence
|
||||
|
||||
`vmagent` stores pending data that cannot be sent to the configured remote storage systems in a timely manner.
|
||||
`vmagent` [stores pending data that cannot be sent to the configured remote storage systems](https://victoriametrics.com/blog/vmagent-key-features-explained/#persistent-disk-for-remote-write) in a timely manner.
|
||||
By default, `vmagent` writes all the pending data to the folder configured via `-remoteWrite.tmpDataPath` cmd-line flag
|
||||
until this data is sent to the configured `-remoteWrite.url` systems or until the folder becomes full.
|
||||
The maximum data size that can be saved to `-remoteWrite.tmpDataPath` per every configured `-remoteWrite.url` can be
|
||||
@@ -996,7 +1001,7 @@ moment it becomes visible at the remote storage.
|
||||
|
||||
This behavior can be changed with the `-remoteWrite.inmemoryQueues` {{% available_from "v1.146.0" %}} command-line flag.
|
||||
When set to a non-zero value, vmagent starts the given number of additional workers,
|
||||
which send only recently ingested data from the in-memory queue, while the workers configured via `-remoteWrite.queues` drain the file-based backlog concurrently.
|
||||
which send only recently ingested data from the [in-memory queue](https://victoriametrics.com/blog/vmagent-how-it-works/#in-memory-queue), while the workers configured via `-remoteWrite.queues` drain the file-based backlog concurrently.
|
||||
This reduces the delivery lag for fresh samples after remote storage outages or slowdowns. The flag can be set individually per each `-remoteWrite.url`.
|
||||
|
||||
Note that these workers are started in addition to the workers configured via `-remoteWrite.queues`, so the total number of concurrent connections to
|
||||
|
||||
@@ -209,6 +209,8 @@ rules:
|
||||
[ debug: <bool> | default = false ]
|
||||
```
|
||||
|
||||
See a blogpost about [how rule groups work](https://victoriametrics.com/blog/alerting-recording-rules-alertmanager/#groups).
|
||||
|
||||
### Rules
|
||||
|
||||
Every rule contains an `expr` field for the expression to evaluate against the configured datasource.
|
||||
@@ -285,6 +287,8 @@ annotations:
|
||||
[ <labelname>: <tmpl_string> ]
|
||||
```
|
||||
|
||||
See a blogpost about [how alerting rules work](https://victoriametrics.com/blog/alerting-recording-rules-alertmanager/#alerting-rules).
|
||||
|
||||
#### Recording rules
|
||||
|
||||
The syntax for recording rules is the following:
|
||||
@@ -322,10 +326,13 @@ labels:
|
||||
|
||||
For recording rules to work `-remoteWrite.url` must be specified.
|
||||
|
||||
See a blogpost about [how recording rules work](https://victoriametrics.com/blog/alerting-recording-rules-alertmanager/#recording-rules).
|
||||
|
||||
## Templating
|
||||
|
||||
It is allowed to use [Go templating](https://golang.org/pkg/text/template/) in annotations and labels(with limited support) to format data, iterate over
|
||||
or execute expressions.
|
||||
See a blogpost about [templating alerts](https://victoriametrics.com/blog/alerting-recording-rules-alertmanager/#templates).
|
||||
The following variables are available in templating:
|
||||
|
||||
| Variable | Description | Example |
|
||||
@@ -928,7 +935,7 @@ See full description for these flags in `./vmalert -help`.
|
||||
|
||||
## Unit Testing for Rules
|
||||
|
||||
You can use `vmalert-tool` to test your alerting and recording rules like [promtool does](https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/).
|
||||
You can use `vmalert-tool` to [test your alerting and recording rules](https://victoriametrics.com/blog/alerting-best-practices/#testing-alerts) like [promtool does](https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/).
|
||||
See more details in [vmalert-tool](https://docs.victoriametrics.com/victoriametrics/vmalert-tool/#unit-testing-for-rules).
|
||||
|
||||
## Monitoring
|
||||
@@ -982,6 +989,8 @@ Try the following tips to avoid common issues:
|
||||
In that case, the default step will be used (`-datasource.queryStep`) and may cause unexpected results compared to
|
||||
executing this query in vmui/Grafana, where step is adjusted differently.
|
||||
|
||||
See a blogpost about [reducing alert noise](https://victoriametrics.com/blog/alerting-best-practices/#reducing-noise).
|
||||
|
||||
### Rule state
|
||||
|
||||
vmalert keeps the last `-rule.updateEntriesLimit` updates (or `update_entries_limit` [per-rule config](https://docs.victoriametrics.com/victoriametrics/vmalert/#alerting-rules))
|
||||
@@ -1037,6 +1046,8 @@ Sometimes, it's hard to understand why a specific alert fired or not. Keep in mi
|
||||
If evaluation returns error (i.e. datasource is unavailable), alert state doesn't change.
|
||||
If at least one evaluation returns no data, then alert's `for` state resets.
|
||||
|
||||
See a blogpost about [tuning the `for` param](https://victoriametrics.com/blog/alerting-best-practices/#the-for-param).
|
||||
|
||||
> Note: The alert state is tracked separately for each time series returned during evaluation.
|
||||
> For example, if the 1st evaluation returns series A and B, and the 2nd evaluation returns only B – the alert will remain active **only for B**.
|
||||
|
||||
@@ -1110,6 +1121,8 @@ How to reduce the chance for a rule to flap:
|
||||
|
||||
See [common mistakes](#common-mistakes) for rules config.
|
||||
|
||||
See a blogpost about [tuning `keep_firing_for`](https://victoriametrics.com/blog/alerting-best-practices/#the-keep_firing_for-param).
|
||||
|
||||
### Never-firing alerts
|
||||
|
||||
vmalert can detect {{% available_from "v1.91.0" %}} if alert's expression doesn't match any time series in runtime.
|
||||
@@ -1360,6 +1373,8 @@ The list of configured or discovered Notifiers can be explored via [UI](#web).
|
||||
If Alertmanager runs in cluster mode then all its URLs needs to be available during discovery
|
||||
to ensure [high availability](https://github.com/prometheus/alertmanager#high-availability).
|
||||
|
||||
See a blogpost about [how Alertmanager processes alerts](https://victoriametrics.com/blog/alerting-recording-rules-alertmanager/#alertmanager).
|
||||
|
||||
The configuration file [specification](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/notifier/config.go)
|
||||
is the following:
|
||||
|
||||
|
||||
@@ -9,48 +9,47 @@ import (
|
||||
)
|
||||
|
||||
// WriteMetricRelabelDebug writes /metric-relabel-debug page to w with the corresponding args.
|
||||
func WriteMetricRelabelDebug(w io.Writer, targetID, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, format string, err error) {
|
||||
writeRelabelDebug(w, false, targetID, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, format, err)
|
||||
func WriteMetricRelabelDebug(w io.Writer, targetID, metric, relabelConfigs, format string, err error) {
|
||||
writeRelabelDebug(w, false, targetID, metric, relabelConfigs, format, err)
|
||||
}
|
||||
|
||||
// WriteTargetRelabelDebug writes /target-relabel-debug page to w with the corresponding args.
|
||||
func WriteTargetRelabelDebug(w io.Writer, targetID, metric, relabelConfigs, format string, err error) {
|
||||
writeRelabelDebug(w, true, targetID, metric, relabelConfigs, 0, 0, format, err)
|
||||
writeRelabelDebug(w, true, targetID, metric, relabelConfigs, format, err)
|
||||
}
|
||||
|
||||
func writeRelabelDebug(w io.Writer, isTargetRelabel bool, targetID, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, format string, err error) {
|
||||
func writeRelabelDebug(w io.Writer, isTargetRelabel bool, targetID, metric, relabelConfigs, format string, err error) {
|
||||
if metric == "" {
|
||||
metric = "{}"
|
||||
}
|
||||
targetURL := ""
|
||||
if err != nil {
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, err)
|
||||
return
|
||||
}
|
||||
|
||||
metric, err = normalizeInputLabels(metric)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("cannot parse metric: %w", err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, err)
|
||||
return
|
||||
}
|
||||
|
||||
labels, err := promutil.NewLabelsFromString(metric)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("cannot parse metric: %w", err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, err)
|
||||
return
|
||||
}
|
||||
|
||||
pcs, err := ParseRelabelConfigsData([]byte(relabelConfigs))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("cannot parse relabel configs: %w", err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, nil, metric, relabelConfigs, err)
|
||||
return
|
||||
}
|
||||
|
||||
dss, targetURL := newDebugRelabelSteps(pcs, labels, isTargetRelabel)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, nil)
|
||||
WriteRelabelDebugSteps(w, targetURL, targetID, format, dss, metric, relabelConfigs, nil)
|
||||
}
|
||||
|
||||
func newDebugRelabelSteps(pcs *ParsedConfigs, labels *promutil.Labels, isTargetRelabel bool) ([]DebugStep, string) {
|
||||
@@ -141,10 +140,6 @@ func getChangedLabelNames(in, out *promutil.Labels) map[string]struct{} {
|
||||
func normalizeInputLabels(metric string) (string, error) {
|
||||
metric = strings.TrimSpace(metric)
|
||||
|
||||
if strings.ContainsRune(metric, '\n') {
|
||||
return metric, fmt.Errorf("only one time series is allowed; got multiple lines")
|
||||
}
|
||||
|
||||
openBrace := strings.Contains(metric, `{`)
|
||||
closeBrace := strings.Contains(metric, `}`)
|
||||
|
||||
|
||||
@@ -6,66 +6,37 @@
|
||||
|
||||
{% stripspace %}
|
||||
|
||||
{% func RelabelDebugSteps(targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) %}
|
||||
{% func RelabelDebugSteps(targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, err error) %}
|
||||
{% if format == "json" %}
|
||||
{%= RelabelDebugStepsJSON(targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err) %}
|
||||
{%= RelabelDebugStepsJSON(targetURL, targetID, dss, metric, relabelConfigs, err) %}
|
||||
{% else %}
|
||||
{%= RelabelDebugStepsHTML(targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err) %}
|
||||
{%= RelabelDebugStepsHTML(targetURL, targetID, dss, metric, relabelConfigs, err) %}
|
||||
{% endif %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func RelabelDebugStepsHTML(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) %}
|
||||
{% func RelabelDebugStepsHTML(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{%= htmlcomponents.CommonHeader() %}
|
||||
<title>Metric relabel debug</title>
|
||||
<script>
|
||||
function setRelabelDebugFormMethod(form) {
|
||||
form.method = (form.elements["relabel_configs"].value.length + form.elements["metric"].value.length > 1000) ? "POST" : "GET";
|
||||
}
|
||||
|
||||
function reloadRelabelConfigs(select) {
|
||||
if (!confirm('Reload will discard all modifications to the current configuration. Continue?')) {
|
||||
select.value = select.prevValue;
|
||||
return;
|
||||
function submitRelabelDebugForm(e) {
|
||||
var form = e.target;
|
||||
var method = "GET";
|
||||
if (form.elements["relabel_configs"].value.length + form.elements["metric"].value.length > 1000) {
|
||||
method = "POST";
|
||||
}
|
||||
document.getElementById('reload_url_relabel_configs').value = '1';
|
||||
setRelabelDebugFormMethod(select.form);
|
||||
select.form.submit();
|
||||
form.method = method;
|
||||
}
|
||||
|
||||
function initRelabelConfigsHighlight() {
|
||||
var ta = document.getElementById('relabel-configs-input');
|
||||
var bd = document.getElementById('relabel-configs-backdrop');
|
||||
if (!ta || !bd) return;
|
||||
function escapeHtml(s) {
|
||||
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||
}
|
||||
function highlight(text) {
|
||||
return text.split('\n').map(function(line) {
|
||||
var e = escapeHtml(line);
|
||||
return /^\s*#/.test(line)
|
||||
? '<span style="color:#999">'+e+'</span>'
|
||||
: '<span style="color:#212529">'+e+'</span>';
|
||||
}).join('\n');
|
||||
}
|
||||
function update() { bd.innerHTML = highlight(ta.value)+'\n'; }
|
||||
ta.addEventListener('input', update);
|
||||
ta.addEventListener('scroll', function() { bd.scrollTop = ta.scrollTop; });
|
||||
update();
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', initRelabelConfigsHighlight);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
{%= htmlcomponents.Navbar() %}
|
||||
<div class="container-fluid">
|
||||
<a href="https://docs.victoriametrics.com/victoriametrics/relabeling/" target="_blank">Relabeling Cookbook</a>{% space %}|{% space %}
|
||||
<a href="https://docs.victoriametrics.com/victoriametrics/relabeling/#relabeling-stages" target="_blank">Relabeling Stages</a>
|
||||
<a href="https://docs.victoriametrics.com/victoriametrics/relabeling/" target="_blank">Relabeling docs</a>{% space %}
|
||||
|
||||
{% if targetID != "" %}
|
||||
{% space %}|{% space %}
|
||||
{% if targetURL != "" %}
|
||||
<a href="metric-relabel-debug?id={%s targetID %}">Metric relabel debug</a>
|
||||
{% else %}
|
||||
@@ -79,14 +50,14 @@ document.addEventListener('DOMContentLoaded', initRelabelConfigsHighlight);
|
||||
{% endif %}
|
||||
|
||||
<div class="m-3">
|
||||
<form method="POST" onsubmit="setRelabelDebugFormMethod(this)">
|
||||
{%= relabelDebugFormInputs(metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, targetID) %}
|
||||
<form method="POST" onsubmit="submitRelabelDebugForm(event)">
|
||||
{%= relabelDebugFormInputs(metric, relabelConfigs) %}
|
||||
{% if targetID != "" %}
|
||||
<input type="hidden" name="id" value="{%s targetID %}" />
|
||||
{% endif %}
|
||||
<input type="submit" value="Submit" class="btn btn-primary m-1" />
|
||||
{% if targetID != "" %}
|
||||
<button type="button" onclick="location.href='?id={%s targetID %}'" class="btn btn-secondary m-1">Reset All</button>
|
||||
<button type="button" onclick="location.href='?id={%s targetID %}'" class="btn btn-secondary m-1">Reset</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
@@ -101,44 +72,15 @@ document.addEventListener('DOMContentLoaded', initRelabelConfigsHighlight);
|
||||
</html>
|
||||
{% endfunc %}
|
||||
|
||||
{% func relabelDebugFormInputs(metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, targetID string) %}
|
||||
{% func relabelDebugFormInputs(metric, relabelConfigs string) %}
|
||||
<div>
|
||||
<!-- show remote write relabel reload only for scrape metric relabel debug and pure relabel debug. discovery debug should not display this section -->
|
||||
{% if !isTargetRelabel %}
|
||||
<div>
|
||||
<div class="m-1">
|
||||
<div class="d-flex align-items-center gap-2 mt-1">
|
||||
Configs:
|
||||
{% if urlRelabelIndexLength > 0 %}
|
||||
<input type="hidden" name="reload_url_relabel_configs" id="reload_url_relabel_configs" value="" />
|
||||
<select name="url_relabel_configs_index" class="form-select form-select-sm w-auto" onfocus="this.prevValue=this.value" onchange="reloadRelabelConfigs(this)">
|
||||
{% for i := range urlRelabelIndexLength %}
|
||||
{% if urlRelabelIndexCurrent == i %}
|
||||
<option value="{%d i %}" selected="selected">remote-write-url-{%d i %}</option>
|
||||
{% else %}
|
||||
<option value="{%d i %}">remote-write-url-{%d i %}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
Configs:
|
||||
{% endif %}
|
||||
|
||||
<!-- the following text area css was generated with the help of AI to display yaml comments (starting with #) in gray. it could be rewritten in the future -->
|
||||
<div class="m-1" style="position:relative;height:15em;">
|
||||
<div id="relabel-configs-backdrop" style="position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;font-family:monospace;white-space:pre-wrap;padding:0.375rem 0.75rem;border:1px solid transparent;"></div>
|
||||
<textarea id="relabel-configs-input" name="relabel_configs" class="form-control" style="position:absolute;top:0;left:0;height:100%;font-family:monospace;color:transparent;caret-color:#212529;background:transparent;resize:none;overflow-y:scroll;">
|
||||
{%s relabelConfigs %}
|
||||
</textarea>
|
||||
</div>
|
||||
Relabel configs:<br/>
|
||||
<textarea name="relabel_configs" style="width: 100%; height: 15em; font-family: monospace" class="m-1">{%s relabelConfigs %}</textarea>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
One Time Series:<br/>
|
||||
<textarea name="metric" style="width: 100%; height: 5em; font-family: monospace" class="m-1" placeholder="up{job="job_name",instance="host:port"}">{%s metric %}</textarea>
|
||||
|
||||
<div>
|
||||
Labels:<br/>
|
||||
<textarea name="metric" style="width: 100%; height: 5em; font-family: monospace" class="m-1">{%s metric %}</textarea>
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
||||
@@ -211,7 +153,7 @@ document.addEventListener('DOMContentLoaded', initRelabelConfigsHighlight);
|
||||
{% endif %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func RelabelDebugStepsJSON(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) %}
|
||||
{% func RelabelDebugStepsJSON(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) %}
|
||||
{
|
||||
{% if err != nil %}
|
||||
"status": "error",
|
||||
|
||||
@@ -25,37 +25,37 @@ var (
|
||||
)
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:9
|
||||
func StreamRelabelDebugSteps(qw422016 *qt422016.Writer, targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) {
|
||||
func StreamRelabelDebugSteps(qw422016 *qt422016.Writer, targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:10
|
||||
if format == "json" {
|
||||
//line lib/promrelabel/debug.qtpl:11
|
||||
StreamRelabelDebugStepsJSON(qw422016, targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
StreamRelabelDebugStepsJSON(qw422016, targetURL, targetID, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:12
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:13
|
||||
StreamRelabelDebugStepsHTML(qw422016, targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
StreamRelabelDebugStepsHTML(qw422016, targetURL, targetID, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:14
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
func WriteRelabelDebugSteps(qq422016 qtio422016.Writer, targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) {
|
||||
func WriteRelabelDebugSteps(qq422016 qtio422016.Writer, targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
StreamRelabelDebugSteps(qw422016, targetURL, targetID, format, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
StreamRelabelDebugSteps(qw422016, targetURL, targetID, format, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
func RelabelDebugSteps(targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) string {
|
||||
func RelabelDebugSteps(targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, err error) string {
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
WriteRelabelDebugSteps(qb422016, targetURL, targetID, format, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
WriteRelabelDebugSteps(qb422016, targetURL, targetID, format, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:15
|
||||
@@ -66,495 +66,431 @@ func RelabelDebugSteps(targetURL, targetID, format string, dss []DebugStep, metr
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:17
|
||||
func StreamRelabelDebugStepsHTML(qw422016 *qt422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) {
|
||||
func StreamRelabelDebugStepsHTML(qw422016 *qt422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:17
|
||||
qw422016.N().S(`<!DOCTYPE html><html lang="en"><head>`)
|
||||
//line lib/promrelabel/debug.qtpl:21
|
||||
htmlcomponents.StreamCommonHeader(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:21
|
||||
qw422016.N().S(`<title>Metric relabel debug</title><script>function setRelabelDebugFormMethod(form) {form.method = (form.elements["relabel_configs"].value.length + form.elements["metric"].value.length > 1000) ? "POST" : "GET";}function reloadRelabelConfigs(select) {if (!confirm('Reload will discard all modifications to the current configuration. Continue?')) {select.value = select.prevValue;return;}document.getElementById('reload_url_relabel_configs').value = '1';setRelabelDebugFormMethod(select.form);select.form.submit();}function initRelabelConfigsHighlight() {var ta = document.getElementById('relabel-configs-input');var bd = document.getElementById('relabel-configs-backdrop');if (!ta || !bd) return;function escapeHtml(s) {return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');}function highlight(text) {return text.split('\n').map(function(line) {var e = escapeHtml(line);return /^\s*#/.test(line)? '<span style="color:#999">'+e+'</span>': '<span style="color:#212529">'+e+'</span>';}).join('\n');}function update() { bd.innerHTML = highlight(ta.value)+'\n'; }ta.addEventListener('input', update);ta.addEventListener('scroll', function() { bd.scrollTop = ta.scrollTop; });update();}document.addEventListener('DOMContentLoaded', initRelabelConfigsHighlight);</script></head><body>`)
|
||||
//line lib/promrelabel/debug.qtpl:62
|
||||
qw422016.N().S(`<title>Metric relabel debug</title><script>function submitRelabelDebugForm(e) {var form = e.target;var method = "GET";if (form.elements["relabel_configs"].value.length + form.elements["metric"].value.length > 1000) {method = "POST";}form.method = method;}</script></head><body>`)
|
||||
//line lib/promrelabel/debug.qtpl:35
|
||||
htmlcomponents.StreamNavbar(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:62
|
||||
qw422016.N().S(`<div class="container-fluid"><a href="https://docs.victoriametrics.com/victoriametrics/relabeling/" target="_blank">Relabeling Cookbook</a>`)
|
||||
//line lib/promrelabel/debug.qtpl:64
|
||||
//line lib/promrelabel/debug.qtpl:35
|
||||
qw422016.N().S(`<div class="container-fluid"><a href="https://docs.victoriametrics.com/victoriametrics/relabeling/" target="_blank">Relabeling docs</a>`)
|
||||
//line lib/promrelabel/debug.qtpl:37
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:64
|
||||
qw422016.N().S(`|`)
|
||||
//line lib/promrelabel/debug.qtpl:64
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:64
|
||||
qw422016.N().S(`<a href="https://docs.victoriametrics.com/victoriametrics/relabeling/#relabeling-stages" target="_blank">Relabeling Stages</a>`)
|
||||
//line lib/promrelabel/debug.qtpl:67
|
||||
//line lib/promrelabel/debug.qtpl:39
|
||||
if targetID != "" {
|
||||
//line lib/promrelabel/debug.qtpl:68
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:68
|
||||
qw422016.N().S(`|`)
|
||||
//line lib/promrelabel/debug.qtpl:68
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:69
|
||||
//line lib/promrelabel/debug.qtpl:40
|
||||
if targetURL != "" {
|
||||
//line lib/promrelabel/debug.qtpl:69
|
||||
//line lib/promrelabel/debug.qtpl:40
|
||||
qw422016.N().S(`<a href="metric-relabel-debug?id=`)
|
||||
//line lib/promrelabel/debug.qtpl:70
|
||||
//line lib/promrelabel/debug.qtpl:41
|
||||
qw422016.E().S(targetID)
|
||||
//line lib/promrelabel/debug.qtpl:70
|
||||
//line lib/promrelabel/debug.qtpl:41
|
||||
qw422016.N().S(`">Metric relabel debug</a>`)
|
||||
//line lib/promrelabel/debug.qtpl:71
|
||||
//line lib/promrelabel/debug.qtpl:42
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:71
|
||||
//line lib/promrelabel/debug.qtpl:42
|
||||
qw422016.N().S(`<a href="target-relabel-debug?id=`)
|
||||
//line lib/promrelabel/debug.qtpl:72
|
||||
//line lib/promrelabel/debug.qtpl:43
|
||||
qw422016.E().S(targetID)
|
||||
//line lib/promrelabel/debug.qtpl:72
|
||||
//line lib/promrelabel/debug.qtpl:43
|
||||
qw422016.N().S(`">Target relabel debug</a>`)
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
//line lib/promrelabel/debug.qtpl:44
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:74
|
||||
//line lib/promrelabel/debug.qtpl:45
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:74
|
||||
//line lib/promrelabel/debug.qtpl:45
|
||||
qw422016.N().S(`<br>`)
|
||||
//line lib/promrelabel/debug.qtpl:77
|
||||
//line lib/promrelabel/debug.qtpl:48
|
||||
if err != nil {
|
||||
//line lib/promrelabel/debug.qtpl:78
|
||||
//line lib/promrelabel/debug.qtpl:49
|
||||
htmlcomponents.StreamErrorNotification(qw422016, err)
|
||||
//line lib/promrelabel/debug.qtpl:79
|
||||
//line lib/promrelabel/debug.qtpl:50
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:79
|
||||
qw422016.N().S(`<div class="m-3"><form method="POST" onsubmit="setRelabelDebugFormMethod(this)">`)
|
||||
//line lib/promrelabel/debug.qtpl:83
|
||||
streamrelabelDebugFormInputs(qw422016, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, targetID)
|
||||
//line lib/promrelabel/debug.qtpl:84
|
||||
//line lib/promrelabel/debug.qtpl:50
|
||||
qw422016.N().S(`<div class="m-3"><form method="POST" onsubmit="submitRelabelDebugForm(event)">`)
|
||||
//line lib/promrelabel/debug.qtpl:54
|
||||
streamrelabelDebugFormInputs(qw422016, metric, relabelConfigs)
|
||||
//line lib/promrelabel/debug.qtpl:55
|
||||
if targetID != "" {
|
||||
//line lib/promrelabel/debug.qtpl:84
|
||||
//line lib/promrelabel/debug.qtpl:55
|
||||
qw422016.N().S(`<input type="hidden" name="id" value="`)
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
//line lib/promrelabel/debug.qtpl:56
|
||||
qw422016.E().S(targetID)
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
//line lib/promrelabel/debug.qtpl:56
|
||||
qw422016.N().S(`" />`)
|
||||
//line lib/promrelabel/debug.qtpl:86
|
||||
//line lib/promrelabel/debug.qtpl:57
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:86
|
||||
//line lib/promrelabel/debug.qtpl:57
|
||||
qw422016.N().S(`<input type="submit" value="Submit" class="btn btn-primary m-1" />`)
|
||||
//line lib/promrelabel/debug.qtpl:88
|
||||
//line lib/promrelabel/debug.qtpl:59
|
||||
if targetID != "" {
|
||||
//line lib/promrelabel/debug.qtpl:88
|
||||
//line lib/promrelabel/debug.qtpl:59
|
||||
qw422016.N().S(`<button type="button" onclick="location.href='?id=`)
|
||||
//line lib/promrelabel/debug.qtpl:89
|
||||
//line lib/promrelabel/debug.qtpl:60
|
||||
qw422016.E().S(targetID)
|
||||
//line lib/promrelabel/debug.qtpl:89
|
||||
qw422016.N().S(`'" class="btn btn-secondary m-1">Reset All</button>`)
|
||||
//line lib/promrelabel/debug.qtpl:90
|
||||
//line lib/promrelabel/debug.qtpl:60
|
||||
qw422016.N().S(`'" class="btn btn-secondary m-1">Reset</button>`)
|
||||
//line lib/promrelabel/debug.qtpl:61
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:90
|
||||
//line lib/promrelabel/debug.qtpl:61
|
||||
qw422016.N().S(`</form></div><div class="row"><main class="col-12">`)
|
||||
//line lib/promrelabel/debug.qtpl:96
|
||||
//line lib/promrelabel/debug.qtpl:67
|
||||
streamrelabelDebugSteps(qw422016, dss, targetURL, targetID)
|
||||
//line lib/promrelabel/debug.qtpl:96
|
||||
//line lib/promrelabel/debug.qtpl:67
|
||||
qw422016.N().S(`</main></div></div></body></html>`)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
func WriteRelabelDebugStepsHTML(qq422016 qtio422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
func WriteRelabelDebugStepsHTML(qq422016 qtio422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
StreamRelabelDebugStepsHTML(qw422016, targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
StreamRelabelDebugStepsHTML(qw422016, targetURL, targetID, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
func RelabelDebugStepsHTML(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) string {
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
func RelabelDebugStepsHTML(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) string {
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
WriteRelabelDebugStepsHTML(qb422016, targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
WriteRelabelDebugStepsHTML(qb422016, targetURL, targetID, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
return qs422016
|
||||
//line lib/promrelabel/debug.qtpl:102
|
||||
//line lib/promrelabel/debug.qtpl:73
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:104
|
||||
func streamrelabelDebugFormInputs(qw422016 *qt422016.Writer, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, targetID string) {
|
||||
//line lib/promrelabel/debug.qtpl:104
|
||||
qw422016.N().S(`<div><!-- show remote write relabel reload only for scrape metric relabel debug and pure relabel debug. discovery debug should not display this section -->`)
|
||||
//line lib/promrelabel/debug.qtpl:107
|
||||
if !isTargetRelabel {
|
||||
//line lib/promrelabel/debug.qtpl:107
|
||||
qw422016.N().S(`<div><div class="m-1"><div class="d-flex align-items-center gap-2 mt-1">Configs:`)
|
||||
//line lib/promrelabel/debug.qtpl:112
|
||||
if urlRelabelIndexLength > 0 {
|
||||
//line lib/promrelabel/debug.qtpl:112
|
||||
qw422016.N().S(`<input type="hidden" name="reload_url_relabel_configs" id="reload_url_relabel_configs" value="" /><select name="url_relabel_configs_index" class="form-select form-select-sm w-auto" onfocus="this.prevValue=this.value" onchange="reloadRelabelConfigs(this)">`)
|
||||
//line lib/promrelabel/debug.qtpl:115
|
||||
for i := range urlRelabelIndexLength {
|
||||
//line lib/promrelabel/debug.qtpl:116
|
||||
if urlRelabelIndexCurrent == i {
|
||||
//line lib/promrelabel/debug.qtpl:116
|
||||
qw422016.N().S(`<option value="`)
|
||||
//line lib/promrelabel/debug.qtpl:117
|
||||
qw422016.N().D(i)
|
||||
//line lib/promrelabel/debug.qtpl:117
|
||||
qw422016.N().S(`" selected="selected">remote-write-url-`)
|
||||
//line lib/promrelabel/debug.qtpl:117
|
||||
qw422016.N().D(i)
|
||||
//line lib/promrelabel/debug.qtpl:117
|
||||
qw422016.N().S(`</option>`)
|
||||
//line lib/promrelabel/debug.qtpl:118
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:118
|
||||
qw422016.N().S(`<option value="`)
|
||||
//line lib/promrelabel/debug.qtpl:119
|
||||
qw422016.N().D(i)
|
||||
//line lib/promrelabel/debug.qtpl:119
|
||||
qw422016.N().S(`">remote-write-url-`)
|
||||
//line lib/promrelabel/debug.qtpl:119
|
||||
qw422016.N().D(i)
|
||||
//line lib/promrelabel/debug.qtpl:119
|
||||
qw422016.N().S(`</option>`)
|
||||
//line lib/promrelabel/debug.qtpl:120
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:121
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:121
|
||||
qw422016.N().S(`</select>`)
|
||||
//line lib/promrelabel/debug.qtpl:123
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:123
|
||||
qw422016.N().S(`</div></div></div>`)
|
||||
//line lib/promrelabel/debug.qtpl:127
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:127
|
||||
qw422016.N().S(`Configs:`)
|
||||
//line lib/promrelabel/debug.qtpl:129
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:129
|
||||
qw422016.N().S(`<!-- the following text area css was generated with the help of AI to display yaml comments (starting with #) in gray. it could be rewritten in the future --><div class="m-1" style="position:relative;height:15em;"><div id="relabel-configs-backdrop" style="position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;font-family:monospace;white-space:pre-wrap;padding:0.375rem 0.75rem;border:1px solid transparent;"></div><textarea id="relabel-configs-input" name="relabel_configs" class="form-control" style="position:absolute;top:0;left:0;height:100%;font-family:monospace;color:transparent;caret-color:#212529;background:transparent;resize:none;overflow-y:scroll;">`)
|
||||
//line lib/promrelabel/debug.qtpl:135
|
||||
//line lib/promrelabel/debug.qtpl:75
|
||||
func streamrelabelDebugFormInputs(qw422016 *qt422016.Writer, metric, relabelConfigs string) {
|
||||
//line lib/promrelabel/debug.qtpl:75
|
||||
qw422016.N().S(`<div>Relabel configs:<br/><textarea name="relabel_configs" style="width: 100%; height: 15em; font-family: monospace" class="m-1">`)
|
||||
//line lib/promrelabel/debug.qtpl:78
|
||||
qw422016.E().S(relabelConfigs)
|
||||
//line lib/promrelabel/debug.qtpl:135
|
||||
qw422016.N().S(`</textarea></div></div><div class="mt-2">One Time Series:<br/><textarea name="metric" style="width: 100%; height: 5em; font-family: monospace" class="m-1" placeholder="up{job="job_name",instance="host:port"}">`)
|
||||
//line lib/promrelabel/debug.qtpl:141
|
||||
//line lib/promrelabel/debug.qtpl:78
|
||||
qw422016.N().S(`</textarea></div><div>Labels:<br/><textarea name="metric" style="width: 100%; height: 5em; font-family: monospace" class="m-1">`)
|
||||
//line lib/promrelabel/debug.qtpl:83
|
||||
qw422016.E().S(metric)
|
||||
//line lib/promrelabel/debug.qtpl:141
|
||||
//line lib/promrelabel/debug.qtpl:83
|
||||
qw422016.N().S(`</textarea></div>`)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
func writerelabelDebugFormInputs(qq422016 qtio422016.Writer, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, targetID string) {
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
func writerelabelDebugFormInputs(qq422016 qtio422016.Writer, metric, relabelConfigs string) {
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
streamrelabelDebugFormInputs(qw422016, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, targetID)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
streamrelabelDebugFormInputs(qw422016, metric, relabelConfigs)
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
func relabelDebugFormInputs(metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, targetID string) string {
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
func relabelDebugFormInputs(metric, relabelConfigs string) string {
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
writerelabelDebugFormInputs(qb422016, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, targetID)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
writerelabelDebugFormInputs(qb422016, metric, relabelConfigs)
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
return qs422016
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
//line lib/promrelabel/debug.qtpl:85
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
//line lib/promrelabel/debug.qtpl:87
|
||||
func streamrelabelDebugSteps(qw422016 *qt422016.Writer, dss []DebugStep, targetURL, targetID string) {
|
||||
//line lib/promrelabel/debug.qtpl:146
|
||||
//line lib/promrelabel/debug.qtpl:88
|
||||
if len(dss) > 0 {
|
||||
//line lib/promrelabel/debug.qtpl:146
|
||||
//line lib/promrelabel/debug.qtpl:88
|
||||
qw422016.N().S(`<div class="m-3"><b>Original labels:</b> <samp>`)
|
||||
//line lib/promrelabel/debug.qtpl:148
|
||||
//line lib/promrelabel/debug.qtpl:90
|
||||
streammustFormatLabels(qw422016, dss[0].In)
|
||||
//line lib/promrelabel/debug.qtpl:148
|
||||
//line lib/promrelabel/debug.qtpl:90
|
||||
qw422016.N().S(`</samp></div>`)
|
||||
//line lib/promrelabel/debug.qtpl:150
|
||||
//line lib/promrelabel/debug.qtpl:92
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:150
|
||||
//line lib/promrelabel/debug.qtpl:92
|
||||
qw422016.N().S(`<table class="table table-striped table-hover table-bordered table-sm"><thead><tr><th scope="col" style="width: 5%">Step</th><th scope="col" style="width: 25%">Relabeling Rule</th><th scope="col" style="width: 35%">Input Labels</th><th scope="col" stile="width: 35%">Output labels</a></tr></thead><tbody>`)
|
||||
//line lib/promrelabel/debug.qtpl:161
|
||||
//line lib/promrelabel/debug.qtpl:103
|
||||
for i, ds := range dss {
|
||||
//line lib/promrelabel/debug.qtpl:163
|
||||
//line lib/promrelabel/debug.qtpl:105
|
||||
inLabels, inErr := promutil.NewLabelsFromString(ds.In)
|
||||
outLabels, outErr := promutil.NewLabelsFromString(ds.Out)
|
||||
changedLabels := getChangedLabelNames(inLabels, outLabels)
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:166
|
||||
//line lib/promrelabel/debug.qtpl:108
|
||||
qw422016.N().S(`<tr><td>`)
|
||||
//line lib/promrelabel/debug.qtpl:168
|
||||
//line lib/promrelabel/debug.qtpl:110
|
||||
qw422016.N().D(i)
|
||||
//line lib/promrelabel/debug.qtpl:168
|
||||
//line lib/promrelabel/debug.qtpl:110
|
||||
qw422016.N().S(`</td><td><b><pre class="m-2">`)
|
||||
//line lib/promrelabel/debug.qtpl:169
|
||||
//line lib/promrelabel/debug.qtpl:111
|
||||
qw422016.E().S(ds.Rule)
|
||||
//line lib/promrelabel/debug.qtpl:169
|
||||
//line lib/promrelabel/debug.qtpl:111
|
||||
qw422016.N().S(`</pre></b></td><td>`)
|
||||
//line lib/promrelabel/debug.qtpl:171
|
||||
//line lib/promrelabel/debug.qtpl:113
|
||||
if inErr == nil {
|
||||
//line lib/promrelabel/debug.qtpl:171
|
||||
//line lib/promrelabel/debug.qtpl:113
|
||||
qw422016.N().S(`<div class="m-2" style="font-size: 0.9em" title="deleted and updated labels highlighted in red">`)
|
||||
//line lib/promrelabel/debug.qtpl:173
|
||||
//line lib/promrelabel/debug.qtpl:115
|
||||
streamlabelsWithHighlight(qw422016, inLabels, changedLabels, "#D15757")
|
||||
//line lib/promrelabel/debug.qtpl:173
|
||||
//line lib/promrelabel/debug.qtpl:115
|
||||
qw422016.N().S(`</div>`)
|
||||
//line lib/promrelabel/debug.qtpl:175
|
||||
//line lib/promrelabel/debug.qtpl:117
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:175
|
||||
//line lib/promrelabel/debug.qtpl:117
|
||||
qw422016.N().S(`<div class="m-2" style="font-size: 0.9em; color: red" title="error parsing input labels"><pre>`)
|
||||
//line lib/promrelabel/debug.qtpl:177
|
||||
//line lib/promrelabel/debug.qtpl:119
|
||||
qw422016.E().S(inErr.Error())
|
||||
//line lib/promrelabel/debug.qtpl:177
|
||||
//line lib/promrelabel/debug.qtpl:119
|
||||
qw422016.N().S(`</pre></div>`)
|
||||
//line lib/promrelabel/debug.qtpl:179
|
||||
//line lib/promrelabel/debug.qtpl:121
|
||||
break
|
||||
//line lib/promrelabel/debug.qtpl:180
|
||||
//line lib/promrelabel/debug.qtpl:122
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:180
|
||||
//line lib/promrelabel/debug.qtpl:122
|
||||
qw422016.N().S(`</td><td>`)
|
||||
//line lib/promrelabel/debug.qtpl:183
|
||||
//line lib/promrelabel/debug.qtpl:125
|
||||
if outErr == nil {
|
||||
//line lib/promrelabel/debug.qtpl:183
|
||||
//line lib/promrelabel/debug.qtpl:125
|
||||
qw422016.N().S(`<div class="m-2" style="font-size: 0.9em" title="added and updated labels highlighted in blue">`)
|
||||
//line lib/promrelabel/debug.qtpl:185
|
||||
//line lib/promrelabel/debug.qtpl:127
|
||||
streamlabelsWithHighlight(qw422016, outLabels, changedLabels, "#4495e0")
|
||||
//line lib/promrelabel/debug.qtpl:185
|
||||
//line lib/promrelabel/debug.qtpl:127
|
||||
qw422016.N().S(`</div>`)
|
||||
//line lib/promrelabel/debug.qtpl:187
|
||||
//line lib/promrelabel/debug.qtpl:129
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:187
|
||||
//line lib/promrelabel/debug.qtpl:129
|
||||
qw422016.N().S(`<div class="m-2" style="font-size: 0.9em; color: red" title="error parsing output labels"><pre>`)
|
||||
//line lib/promrelabel/debug.qtpl:189
|
||||
//line lib/promrelabel/debug.qtpl:131
|
||||
qw422016.E().S(outErr.Error())
|
||||
//line lib/promrelabel/debug.qtpl:189
|
||||
//line lib/promrelabel/debug.qtpl:131
|
||||
qw422016.N().S(`</pre></div>`)
|
||||
//line lib/promrelabel/debug.qtpl:191
|
||||
//line lib/promrelabel/debug.qtpl:133
|
||||
break
|
||||
//line lib/promrelabel/debug.qtpl:192
|
||||
//line lib/promrelabel/debug.qtpl:134
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:192
|
||||
//line lib/promrelabel/debug.qtpl:134
|
||||
qw422016.N().S(`</td></tr>`)
|
||||
//line lib/promrelabel/debug.qtpl:195
|
||||
//line lib/promrelabel/debug.qtpl:137
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:195
|
||||
//line lib/promrelabel/debug.qtpl:137
|
||||
qw422016.N().S(`</tbody></table>`)
|
||||
//line lib/promrelabel/debug.qtpl:198
|
||||
//line lib/promrelabel/debug.qtpl:140
|
||||
if len(dss) > 0 {
|
||||
//line lib/promrelabel/debug.qtpl:198
|
||||
//line lib/promrelabel/debug.qtpl:140
|
||||
qw422016.N().S(`<div class="m-3"><b>Resulting labels:</b> <samp>`)
|
||||
//line lib/promrelabel/debug.qtpl:200
|
||||
//line lib/promrelabel/debug.qtpl:142
|
||||
streammustFormatLabels(qw422016, dss[len(dss)-1].Out)
|
||||
//line lib/promrelabel/debug.qtpl:200
|
||||
//line lib/promrelabel/debug.qtpl:142
|
||||
qw422016.N().S(`</samp>`)
|
||||
//line lib/promrelabel/debug.qtpl:201
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
if targetURL != "" {
|
||||
//line lib/promrelabel/debug.qtpl:201
|
||||
//line lib/promrelabel/debug.qtpl:143
|
||||
qw422016.N().S(`<div><b>Target URL:</b>`)
|
||||
//line lib/promrelabel/debug.qtpl:203
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:203
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
qw422016.N().S(`<a href="`)
|
||||
//line lib/promrelabel/debug.qtpl:203
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
qw422016.E().S(targetURL)
|
||||
//line lib/promrelabel/debug.qtpl:203
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
qw422016.N().S(`" target="_blank">`)
|
||||
//line lib/promrelabel/debug.qtpl:203
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
qw422016.E().S(targetURL)
|
||||
//line lib/promrelabel/debug.qtpl:203
|
||||
//line lib/promrelabel/debug.qtpl:145
|
||||
qw422016.N().S(`</a>`)
|
||||
//line lib/promrelabel/debug.qtpl:204
|
||||
//line lib/promrelabel/debug.qtpl:146
|
||||
if targetID != "" {
|
||||
//line lib/promrelabel/debug.qtpl:205
|
||||
//line lib/promrelabel/debug.qtpl:147
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:205
|
||||
//line lib/promrelabel/debug.qtpl:147
|
||||
qw422016.N().S(`(<a href="target_response?id=`)
|
||||
//line lib/promrelabel/debug.qtpl:206
|
||||
//line lib/promrelabel/debug.qtpl:148
|
||||
qw422016.E().S(targetID)
|
||||
//line lib/promrelabel/debug.qtpl:206
|
||||
//line lib/promrelabel/debug.qtpl:148
|
||||
qw422016.N().S(`" target="_blank" title="click to fetch target response on behalf of the scraper">response</a>)`)
|
||||
//line lib/promrelabel/debug.qtpl:207
|
||||
//line lib/promrelabel/debug.qtpl:149
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:207
|
||||
//line lib/promrelabel/debug.qtpl:149
|
||||
qw422016.N().S(`</div>`)
|
||||
//line lib/promrelabel/debug.qtpl:209
|
||||
//line lib/promrelabel/debug.qtpl:151
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:209
|
||||
//line lib/promrelabel/debug.qtpl:151
|
||||
qw422016.N().S(`</div>`)
|
||||
//line lib/promrelabel/debug.qtpl:211
|
||||
//line lib/promrelabel/debug.qtpl:153
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
func writerelabelDebugSteps(qq422016 qtio422016.Writer, dss []DebugStep, targetURL, targetID string) {
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
streamrelabelDebugSteps(qw422016, dss, targetURL, targetID)
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
func relabelDebugSteps(dss []DebugStep, targetURL, targetID string) string {
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
writerelabelDebugSteps(qb422016, dss, targetURL, targetID)
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
return qs422016
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
//line lib/promrelabel/debug.qtpl:154
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:214
|
||||
func StreamRelabelDebugStepsJSON(qw422016 *qt422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:214
|
||||
//line lib/promrelabel/debug.qtpl:156
|
||||
func StreamRelabelDebugStepsJSON(qw422016 *qt422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:156
|
||||
qw422016.N().S(`{`)
|
||||
//line lib/promrelabel/debug.qtpl:216
|
||||
//line lib/promrelabel/debug.qtpl:158
|
||||
if err != nil {
|
||||
//line lib/promrelabel/debug.qtpl:216
|
||||
//line lib/promrelabel/debug.qtpl:158
|
||||
qw422016.N().S(`"status": "error","error":`)
|
||||
//line lib/promrelabel/debug.qtpl:218
|
||||
//line lib/promrelabel/debug.qtpl:160
|
||||
qw422016.N().Q(fmt.Sprintf("Error: %s", err))
|
||||
//line lib/promrelabel/debug.qtpl:219
|
||||
//line lib/promrelabel/debug.qtpl:161
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:220
|
||||
//line lib/promrelabel/debug.qtpl:162
|
||||
var hasError bool
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:220
|
||||
//line lib/promrelabel/debug.qtpl:162
|
||||
qw422016.N().S(`"status": "success","steps": [`)
|
||||
//line lib/promrelabel/debug.qtpl:223
|
||||
//line lib/promrelabel/debug.qtpl:165
|
||||
for i, ds := range dss {
|
||||
//line lib/promrelabel/debug.qtpl:225
|
||||
//line lib/promrelabel/debug.qtpl:167
|
||||
inLabels, inErr := promutil.NewLabelsFromString(ds.In)
|
||||
outLabels, outErr := promutil.NewLabelsFromString(ds.Out)
|
||||
changedLabels := getChangedLabelNames(inLabels, outLabels)
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:228
|
||||
//line lib/promrelabel/debug.qtpl:170
|
||||
qw422016.N().S(`{"inLabels":`)
|
||||
//line lib/promrelabel/debug.qtpl:230
|
||||
//line lib/promrelabel/debug.qtpl:172
|
||||
qw422016.N().Q(labelsWithHighlight(inLabels, changedLabels, "#D15757"))
|
||||
//line lib/promrelabel/debug.qtpl:230
|
||||
//line lib/promrelabel/debug.qtpl:172
|
||||
qw422016.N().S(`,"outLabels":`)
|
||||
//line lib/promrelabel/debug.qtpl:231
|
||||
//line lib/promrelabel/debug.qtpl:173
|
||||
qw422016.N().Q(labelsWithHighlight(outLabels, changedLabels, "#4495e0"))
|
||||
//line lib/promrelabel/debug.qtpl:231
|
||||
//line lib/promrelabel/debug.qtpl:173
|
||||
qw422016.N().S(`,"rule":`)
|
||||
//line lib/promrelabel/debug.qtpl:232
|
||||
//line lib/promrelabel/debug.qtpl:174
|
||||
qw422016.N().Q(ds.Rule)
|
||||
//line lib/promrelabel/debug.qtpl:232
|
||||
//line lib/promrelabel/debug.qtpl:174
|
||||
qw422016.N().S(`,"errors": {`)
|
||||
//line lib/promrelabel/debug.qtpl:234
|
||||
//line lib/promrelabel/debug.qtpl:176
|
||||
if inErr != nil {
|
||||
//line lib/promrelabel/debug.qtpl:234
|
||||
//line lib/promrelabel/debug.qtpl:176
|
||||
qw422016.N().S(`"inLabels":`)
|
||||
//line lib/promrelabel/debug.qtpl:235
|
||||
//line lib/promrelabel/debug.qtpl:177
|
||||
qw422016.N().Q(`<span style="color: #D15757">` + inErr.Error() + `</span>`)
|
||||
//line lib/promrelabel/debug.qtpl:235
|
||||
//line lib/promrelabel/debug.qtpl:177
|
||||
if outErr != nil {
|
||||
//line lib/promrelabel/debug.qtpl:235
|
||||
//line lib/promrelabel/debug.qtpl:177
|
||||
qw422016.N().S(`,`)
|
||||
//line lib/promrelabel/debug.qtpl:235
|
||||
//line lib/promrelabel/debug.qtpl:177
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:236
|
||||
//line lib/promrelabel/debug.qtpl:178
|
||||
hasError = true
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:237
|
||||
//line lib/promrelabel/debug.qtpl:179
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
//line lib/promrelabel/debug.qtpl:180
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:239
|
||||
//line lib/promrelabel/debug.qtpl:181
|
||||
if outErr != nil {
|
||||
//line lib/promrelabel/debug.qtpl:239
|
||||
//line lib/promrelabel/debug.qtpl:181
|
||||
qw422016.N().S(`"outLabels":`)
|
||||
//line lib/promrelabel/debug.qtpl:240
|
||||
//line lib/promrelabel/debug.qtpl:182
|
||||
qw422016.N().Q(`<span style="color: #D15757">` + outErr.Error() + `</span>`)
|
||||
//line lib/promrelabel/debug.qtpl:241
|
||||
//line lib/promrelabel/debug.qtpl:183
|
||||
hasError = true
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:242
|
||||
//line lib/promrelabel/debug.qtpl:184
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:242
|
||||
//line lib/promrelabel/debug.qtpl:184
|
||||
qw422016.N().S(`}}`)
|
||||
//line lib/promrelabel/debug.qtpl:245
|
||||
//line lib/promrelabel/debug.qtpl:187
|
||||
if i != len(dss)-1 {
|
||||
//line lib/promrelabel/debug.qtpl:245
|
||||
//line lib/promrelabel/debug.qtpl:187
|
||||
qw422016.N().S(`,`)
|
||||
//line lib/promrelabel/debug.qtpl:245
|
||||
//line lib/promrelabel/debug.qtpl:187
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:246
|
||||
//line lib/promrelabel/debug.qtpl:188
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:246
|
||||
//line lib/promrelabel/debug.qtpl:188
|
||||
qw422016.N().S(`]`)
|
||||
//line lib/promrelabel/debug.qtpl:248
|
||||
//line lib/promrelabel/debug.qtpl:190
|
||||
if len(dss) > 0 && !hasError {
|
||||
//line lib/promrelabel/debug.qtpl:248
|
||||
//line lib/promrelabel/debug.qtpl:190
|
||||
qw422016.N().S(`,"originalLabels":`)
|
||||
//line lib/promrelabel/debug.qtpl:250
|
||||
//line lib/promrelabel/debug.qtpl:192
|
||||
qw422016.N().Q(mustFormatLabels(dss[0].In))
|
||||
//line lib/promrelabel/debug.qtpl:250
|
||||
//line lib/promrelabel/debug.qtpl:192
|
||||
qw422016.N().S(`,"resultingLabels":`)
|
||||
//line lib/promrelabel/debug.qtpl:251
|
||||
//line lib/promrelabel/debug.qtpl:193
|
||||
qw422016.N().Q(mustFormatLabels(dss[len(dss)-1].Out))
|
||||
//line lib/promrelabel/debug.qtpl:252
|
||||
//line lib/promrelabel/debug.qtpl:194
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:253
|
||||
//line lib/promrelabel/debug.qtpl:195
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:253
|
||||
//line lib/promrelabel/debug.qtpl:195
|
||||
qw422016.N().S(`}`)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
func WriteRelabelDebugStepsJSON(qq422016 qtio422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
func WriteRelabelDebugStepsJSON(qq422016 qtio422016.Writer, targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) {
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
StreamRelabelDebugStepsJSON(qw422016, targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
StreamRelabelDebugStepsJSON(qw422016, targetURL, targetID, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
func RelabelDebugStepsJSON(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, urlRelabelIndexLength, urlRelabelIndexCurrent int, isTargetRelabel bool, err error) string {
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
func RelabelDebugStepsJSON(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) string {
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
WriteRelabelDebugStepsJSON(qb422016, targetURL, targetID, dss, metric, relabelConfigs, urlRelabelIndexLength, urlRelabelIndexCurrent, isTargetRelabel, err)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
WriteRelabelDebugStepsJSON(qb422016, targetURL, targetID, dss, metric, relabelConfigs, err)
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
return qs422016
|
||||
//line lib/promrelabel/debug.qtpl:255
|
||||
//line lib/promrelabel/debug.qtpl:197
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:257
|
||||
//line lib/promrelabel/debug.qtpl:199
|
||||
func streamlabelsWithHighlight(qw422016 *qt422016.Writer, labels *promutil.Labels, highlight map[string]struct{}, color string) {
|
||||
//line lib/promrelabel/debug.qtpl:259
|
||||
//line lib/promrelabel/debug.qtpl:201
|
||||
labelsList := labels.GetLabels()
|
||||
metricName := ""
|
||||
for i, label := range labelsList {
|
||||
@@ -565,153 +501,153 @@ func streamlabelsWithHighlight(qw422016 *qt422016.Writer, labels *promutil.Label
|
||||
}
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:269
|
||||
//line lib/promrelabel/debug.qtpl:211
|
||||
if metricName != "" {
|
||||
//line lib/promrelabel/debug.qtpl:270
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
if _, ok := highlight["__name__"]; ok {
|
||||
//line lib/promrelabel/debug.qtpl:270
|
||||
//line lib/promrelabel/debug.qtpl:212
|
||||
qw422016.N().S(`<span style="font-weight:bold;color:`)
|
||||
//line lib/promrelabel/debug.qtpl:271
|
||||
//line lib/promrelabel/debug.qtpl:213
|
||||
qw422016.E().S(color)
|
||||
//line lib/promrelabel/debug.qtpl:271
|
||||
//line lib/promrelabel/debug.qtpl:213
|
||||
qw422016.N().S(`">`)
|
||||
//line lib/promrelabel/debug.qtpl:271
|
||||
//line lib/promrelabel/debug.qtpl:213
|
||||
qw422016.E().S(metricName)
|
||||
//line lib/promrelabel/debug.qtpl:271
|
||||
//line lib/promrelabel/debug.qtpl:213
|
||||
qw422016.N().S(`</span>`)
|
||||
//line lib/promrelabel/debug.qtpl:272
|
||||
//line lib/promrelabel/debug.qtpl:214
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:273
|
||||
//line lib/promrelabel/debug.qtpl:215
|
||||
qw422016.E().S(metricName)
|
||||
//line lib/promrelabel/debug.qtpl:274
|
||||
//line lib/promrelabel/debug.qtpl:216
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:275
|
||||
//line lib/promrelabel/debug.qtpl:217
|
||||
if len(labelsList) == 0 {
|
||||
//line lib/promrelabel/debug.qtpl:275
|
||||
//line lib/promrelabel/debug.qtpl:217
|
||||
return
|
||||
//line lib/promrelabel/debug.qtpl:275
|
||||
//line lib/promrelabel/debug.qtpl:217
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:276
|
||||
//line lib/promrelabel/debug.qtpl:218
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:276
|
||||
//line lib/promrelabel/debug.qtpl:218
|
||||
qw422016.N().S(`{`)
|
||||
//line lib/promrelabel/debug.qtpl:278
|
||||
//line lib/promrelabel/debug.qtpl:220
|
||||
for i, label := range labelsList {
|
||||
//line lib/promrelabel/debug.qtpl:279
|
||||
//line lib/promrelabel/debug.qtpl:221
|
||||
if _, ok := highlight[label.Name]; ok {
|
||||
//line lib/promrelabel/debug.qtpl:279
|
||||
//line lib/promrelabel/debug.qtpl:221
|
||||
qw422016.N().S(`<span style="font-weight:bold;color:`)
|
||||
//line lib/promrelabel/debug.qtpl:280
|
||||
//line lib/promrelabel/debug.qtpl:222
|
||||
qw422016.E().S(color)
|
||||
//line lib/promrelabel/debug.qtpl:280
|
||||
//line lib/promrelabel/debug.qtpl:222
|
||||
qw422016.N().S(`">`)
|
||||
//line lib/promrelabel/debug.qtpl:280
|
||||
//line lib/promrelabel/debug.qtpl:222
|
||||
qw422016.E().S(label.Name)
|
||||
//line lib/promrelabel/debug.qtpl:280
|
||||
//line lib/promrelabel/debug.qtpl:222
|
||||
qw422016.N().S(`=`)
|
||||
//line lib/promrelabel/debug.qtpl:280
|
||||
//line lib/promrelabel/debug.qtpl:222
|
||||
qw422016.E().Q(label.Value)
|
||||
//line lib/promrelabel/debug.qtpl:280
|
||||
//line lib/promrelabel/debug.qtpl:222
|
||||
qw422016.N().S(`</span>`)
|
||||
//line lib/promrelabel/debug.qtpl:281
|
||||
//line lib/promrelabel/debug.qtpl:223
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:282
|
||||
//line lib/promrelabel/debug.qtpl:224
|
||||
qw422016.E().S(label.Name)
|
||||
//line lib/promrelabel/debug.qtpl:282
|
||||
//line lib/promrelabel/debug.qtpl:224
|
||||
qw422016.N().S(`=`)
|
||||
//line lib/promrelabel/debug.qtpl:282
|
||||
//line lib/promrelabel/debug.qtpl:224
|
||||
qw422016.E().Q(label.Value)
|
||||
//line lib/promrelabel/debug.qtpl:283
|
||||
//line lib/promrelabel/debug.qtpl:225
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:284
|
||||
//line lib/promrelabel/debug.qtpl:226
|
||||
if i < len(labelsList)-1 {
|
||||
//line lib/promrelabel/debug.qtpl:284
|
||||
//line lib/promrelabel/debug.qtpl:226
|
||||
qw422016.N().S(`,`)
|
||||
//line lib/promrelabel/debug.qtpl:284
|
||||
//line lib/promrelabel/debug.qtpl:226
|
||||
qw422016.N().S(` `)
|
||||
//line lib/promrelabel/debug.qtpl:284
|
||||
//line lib/promrelabel/debug.qtpl:226
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:285
|
||||
//line lib/promrelabel/debug.qtpl:227
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:285
|
||||
//line lib/promrelabel/debug.qtpl:227
|
||||
qw422016.N().S(`}`)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
func writelabelsWithHighlight(qq422016 qtio422016.Writer, labels *promutil.Labels, highlight map[string]struct{}, color string) {
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
streamlabelsWithHighlight(qw422016, labels, highlight, color)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
func labelsWithHighlight(labels *promutil.Labels, highlight map[string]struct{}, color string) string {
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
writelabelsWithHighlight(qb422016, labels, highlight, color)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
return qs422016
|
||||
//line lib/promrelabel/debug.qtpl:287
|
||||
//line lib/promrelabel/debug.qtpl:229
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:289
|
||||
//line lib/promrelabel/debug.qtpl:231
|
||||
func streammustFormatLabels(qw422016 *qt422016.Writer, s string) {
|
||||
//line lib/promrelabel/debug.qtpl:290
|
||||
//line lib/promrelabel/debug.qtpl:232
|
||||
labels, err := promutil.NewLabelsFromString(s)
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:291
|
||||
//line lib/promrelabel/debug.qtpl:233
|
||||
if err != nil {
|
||||
//line lib/promrelabel/debug.qtpl:291
|
||||
//line lib/promrelabel/debug.qtpl:233
|
||||
qw422016.N().S(`<span style="color: red" title="error parsing labels:`)
|
||||
//line lib/promrelabel/debug.qtpl:292
|
||||
//line lib/promrelabel/debug.qtpl:234
|
||||
qw422016.E().S(err.Error())
|
||||
//line lib/promrelabel/debug.qtpl:292
|
||||
//line lib/promrelabel/debug.qtpl:234
|
||||
qw422016.N().S(`">`)
|
||||
//line lib/promrelabel/debug.qtpl:292
|
||||
//line lib/promrelabel/debug.qtpl:234
|
||||
qw422016.E().S("error parsing labels: " + err.Error())
|
||||
//line lib/promrelabel/debug.qtpl:292
|
||||
//line lib/promrelabel/debug.qtpl:234
|
||||
qw422016.N().S(`</span>`)
|
||||
//line lib/promrelabel/debug.qtpl:293
|
||||
//line lib/promrelabel/debug.qtpl:235
|
||||
} else {
|
||||
//line lib/promrelabel/debug.qtpl:294
|
||||
//line lib/promrelabel/debug.qtpl:236
|
||||
streamlabelsWithHighlight(qw422016, labels, nil, "")
|
||||
//line lib/promrelabel/debug.qtpl:295
|
||||
//line lib/promrelabel/debug.qtpl:237
|
||||
}
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
func writemustFormatLabels(qq422016 qtio422016.Writer, s string) {
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
streammustFormatLabels(qw422016, s)
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
}
|
||||
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
func mustFormatLabels(s string) string {
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
writemustFormatLabels(qb422016, s)
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
qs422016 := string(qb422016.B)
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
return qs422016
|
||||
//line lib/promrelabel/debug.qtpl:296
|
||||
//line lib/promrelabel/debug.qtpl:238
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
|
||||
// TestWriteRelabelDebugSupportFormats verifies the relabeling debug input, rules and output.
|
||||
func TestWriteRelabelDebugSupportFormats(t *testing.T) {
|
||||
f := func(input, rules, expect string) {
|
||||
f := func(input, rule, expect string) {
|
||||
// execute
|
||||
outputWriter := bytes.NewBuffer(nil)
|
||||
writeRelabelDebug(outputWriter, false, "", input, rules, 0, 0, "json", nil)
|
||||
writeRelabelDebug(outputWriter, false, "", input, rule, "json", nil)
|
||||
|
||||
// the response is in JSON with HTML content, extract the `resultingLabels` in JSON and unescape it.
|
||||
resultingLabels := fastjson.GetString(outputWriter.Bytes(), `resultingLabels`)
|
||||
@@ -41,20 +41,4 @@ func TestWriteRelabelDebugSupportFormats(t *testing.T) {
|
||||
f(`{_name__="metric_name"`, ruleTestParsing, ``)
|
||||
f(`_name__="metric_name}"`, ruleTestParsing, ``)
|
||||
f(`metrics_name}"`, ruleTestParsing, ``)
|
||||
|
||||
// test multiple rules including remote writes
|
||||
// drop all labels and add one in URL relabeling
|
||||
rule1 := `
|
||||
- action: labeldrop
|
||||
regex: "drop_me_metrics_relabel"
|
||||
`
|
||||
rule2 := `
|
||||
- action: labeldrop
|
||||
regex: "drop_me_remote_write_relabel"
|
||||
`
|
||||
rule3 := `
|
||||
- target_label: add_me_url_relabel
|
||||
replacement: added
|
||||
`
|
||||
f(`{__name__="metric_name", drop_me_metrics_relabel="1", drop_me_remote_write_relabel="2"}`, rule1+rule2+rule3, `metric_name{add_me_url_relabel="added"}`)
|
||||
}
|
||||
|
||||
@@ -3,103 +3,34 @@ package promscrape
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutil"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
|
||||
)
|
||||
|
||||
// WriteMetricRelabelDebug serves requests to /metric-relabel-debug page.
|
||||
// remotewrite-related relabel configs could be empty as vmsingle doesn't provide remote write feature.
|
||||
func WriteMetricRelabelDebug(w http.ResponseWriter, r *http.Request, rwGlobalRelabelConfigs string, rwURLRelabelConfigss []string) {
|
||||
// WriteMetricRelabelDebug serves requests to /metric-relabel-debug page
|
||||
func WriteMetricRelabelDebug(w http.ResponseWriter, r *http.Request) {
|
||||
targetID := r.FormValue("id")
|
||||
metric := r.FormValue("metric")
|
||||
relabelConfigs := r.FormValue("relabel_configs")
|
||||
|
||||
// if set, it means user selected another URL from the dropdown and everything will be reloaded.
|
||||
reloadRWURLRelabelConfigs := r.FormValue("reload_url_relabel_configs")
|
||||
rwURLRelabelConfigsIdxStr := r.FormValue("url_relabel_configs_index")
|
||||
|
||||
format := r.FormValue("format")
|
||||
var err error
|
||||
|
||||
// if all per-URL config is empty, it means no per-URL rule is configured.
|
||||
// set it to 0 so the user do not see the options in debug page.
|
||||
rwURLRelabelConfigsLength := 0
|
||||
for _, urlRelabelConfig := range rwURLRelabelConfigss {
|
||||
if urlRelabelConfig != "" {
|
||||
rwURLRelabelConfigsLength = len(rwURLRelabelConfigss)
|
||||
break
|
||||
if metric == "" && relabelConfigs == "" && targetID != "" {
|
||||
pcs, labels, ok := getMetricRelabelContextByTargetID(targetID)
|
||||
if !ok {
|
||||
err = fmt.Errorf("cannot find target for id=%s", targetID)
|
||||
targetID = ""
|
||||
} else {
|
||||
metric = labels.String()
|
||||
relabelConfigs = pcs.String()
|
||||
}
|
||||
}
|
||||
|
||||
rwURLRelabelConfigsIdx, idxErr := strconv.Atoi(rwURLRelabelConfigsIdxStr)
|
||||
if idxErr != nil {
|
||||
rwURLRelabelConfigsIdx = -1
|
||||
}
|
||||
|
||||
// load the initial data with specific remote write URL index (default 0) in 2 cases:
|
||||
// - relabel config is empty. load scrape relabel (if targetID exist) + remote write related relabel (always).
|
||||
// - `reload` is set. load scrape relabel (if targetID exist) + reload remote write related relabel (by the URL index).
|
||||
init := metric == "" && relabelConfigs == "" && reloadRWURLRelabelConfigs == ""
|
||||
reload := reloadRWURLRelabelConfigs != ""
|
||||
if init || reload {
|
||||
// scrape related relabel labels & rules
|
||||
var (
|
||||
pcs = &promrelabel.ParsedConfigs{} // could be empty
|
||||
labels *promutil.Labels
|
||||
ok bool
|
||||
)
|
||||
if targetID != "" {
|
||||
pcs, labels, ok = getMetricRelabelContextByTargetID(targetID)
|
||||
if !ok {
|
||||
err = fmt.Errorf("cannot find target for id=%s", targetID)
|
||||
targetID = ""
|
||||
} else {
|
||||
metric = "up"
|
||||
metric += labels.String()
|
||||
}
|
||||
}
|
||||
|
||||
// general relabel rules (remote write)
|
||||
// set the per-URL remote write relabel according to index, any error will fall back the index to 0.
|
||||
rwURLRelabelConfigs := ""
|
||||
if len(rwURLRelabelConfigss) > 0 {
|
||||
// ignore the error if the input is invalid or exceed the length, and fallback to 0.
|
||||
if rwURLRelabelConfigsIdx < 0 || rwURLRelabelConfigsIdx >= len(rwURLRelabelConfigss) {
|
||||
rwURLRelabelConfigsIdx = 0
|
||||
}
|
||||
rwURLRelabelConfigs = rwURLRelabelConfigss[rwURLRelabelConfigsIdx]
|
||||
}
|
||||
|
||||
relabelConfigs = composeRelabelConfigs(pcs.String(), rwGlobalRelabelConfigs, rwURLRelabelConfigs, rwURLRelabelConfigsIdx)
|
||||
}
|
||||
|
||||
if format == "json" {
|
||||
httpserver.EnableCORS(w, r)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
}
|
||||
promrelabel.WriteMetricRelabelDebug(w, targetID, metric, relabelConfigs, rwURLRelabelConfigsLength, rwURLRelabelConfigsIdx, format, err)
|
||||
}
|
||||
|
||||
func composeRelabelConfigs(relabelConfigs, rwGlobalRelabelConfigs, rwURLRelabelConfigs string, rwURLIdx int) string {
|
||||
if relabelConfigs != "" {
|
||||
relabelConfigs = "# -promscrape.config .scrape_configs[].metric_relabel_configs\n" + relabelConfigs
|
||||
}
|
||||
|
||||
if rwGlobalRelabelConfigs != "" {
|
||||
relabelConfigs += "\n# -remoteWrite.relabelConfig"
|
||||
relabelConfigs += "\n" + rwGlobalRelabelConfigs
|
||||
}
|
||||
|
||||
if rwURLRelabelConfigs != "" {
|
||||
relabelConfigs += fmt.Sprintf("\n# -remoteWrite.urlRelabelConfig=remote-write-url-%d", rwURLIdx)
|
||||
relabelConfigs += "\n" + rwURLRelabelConfigs
|
||||
}
|
||||
|
||||
return relabelConfigs
|
||||
promrelabel.WriteMetricRelabelDebug(w, targetID, metric, relabelConfigs, format, err)
|
||||
}
|
||||
|
||||
// WriteTargetRelabelDebug generates response for /target-relabel-debug page
|
||||
@@ -117,7 +48,7 @@ func WriteTargetRelabelDebug(w http.ResponseWriter, r *http.Request) {
|
||||
targetID = ""
|
||||
} else {
|
||||
metric = labels.labelsString()
|
||||
relabelConfigs = "# -promscrape.config .scrape_configs[].relabel_configs\n" + pcs.String()
|
||||
relabelConfigs = pcs.String()
|
||||
}
|
||||
}
|
||||
if format == "json" {
|
||||
|
||||
@@ -471,25 +471,23 @@ func (pt *partition) AddRows(rows []rawRow) {
|
||||
var isDebug = false
|
||||
|
||||
func (pt *partition) flushRowssToInmemoryParts(rowss [][]rawRow) {
|
||||
if len(rowss) == 0 {
|
||||
var nonEmptyRowss [][]rawRow
|
||||
for _, rows := range rowss {
|
||||
if len(rows) > 0 {
|
||||
nonEmptyRowss = append(nonEmptyRowss, rows)
|
||||
}
|
||||
}
|
||||
if len(nonEmptyRowss) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Convert rowss into in-memory parts.
|
||||
var pwsLock sync.Mutex
|
||||
pws := make([]*partWrapper, 0, len(rowss))
|
||||
pws := make([]*partWrapper, len(nonEmptyRowss))
|
||||
wg := getWaitGroup()
|
||||
for _, rows := range rowss {
|
||||
for i, rows := range nonEmptyRowss {
|
||||
inmemoryPartsConcurrencyCh <- struct{}{}
|
||||
|
||||
wg.Go(func() {
|
||||
pw := pt.createInmemoryPart(rows)
|
||||
if pw != nil {
|
||||
pwsLock.Lock()
|
||||
pws = append(pws, pw)
|
||||
pwsLock.Unlock()
|
||||
}
|
||||
|
||||
pws[i] = pt.mustCreateInmemoryPart(rows)
|
||||
<-inmemoryPartsConcurrencyCh
|
||||
})
|
||||
}
|
||||
@@ -744,9 +742,14 @@ func (pt *partition) mustMergeInmemoryPartsFinal(pws []*partWrapper) *partWrappe
|
||||
return newPartWrapperFromInmemoryPart(mpDst, flushToDiskDeadline)
|
||||
}
|
||||
|
||||
func (pt *partition) createInmemoryPart(rows []rawRow) *partWrapper {
|
||||
// mustCreateInmemoryPart creates a new in-memory part from rawRows.
|
||||
//
|
||||
// The number of rawRows cannot be zero. Otherwise the method will panic.
|
||||
//
|
||||
// The returned value is always a non-nil partWrapper.
|
||||
func (pt *partition) mustCreateInmemoryPart(rows []rawRow) *partWrapper {
|
||||
if len(rows) == 0 {
|
||||
return nil
|
||||
logger.Panicf("BUG: a part cannot be created from 0 rawRows")
|
||||
}
|
||||
mp := getInmemoryPart()
|
||||
mp.InitFromRows(rows)
|
||||
|
||||
Reference in New Issue
Block a user