mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-05-17 08:36:55 +03:00
### Describe Your Changes Previously, invalid label name or value could cause a panic of vmselect or vmsingle as it was using MustNewLabelsFromString which was added for usage in tests only. Fix this by properly handling and propagating error to user interface if there is any. See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8661 Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
239 lines
9.2 KiB
Plaintext
239 lines
9.2 KiB
Plaintext
{% import (
|
|
"fmt"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/htmlcomponents"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutil"
|
|
) %}
|
|
|
|
{% stripspace %}
|
|
|
|
{% func RelabelDebugSteps(targetURL, targetID, format string, dss []DebugStep, metric, relabelConfigs string, err error) %}
|
|
{% if format == "json" %}
|
|
{%= RelabelDebugStepsJSON(targetURL, targetID, dss, metric, relabelConfigs, err) %}
|
|
{% else %}
|
|
{%= RelabelDebugStepsHTML(targetURL, targetID, dss, metric, relabelConfigs, err) %}
|
|
{% endif %}
|
|
{% endfunc %}
|
|
|
|
{% 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 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>
|
|
{%= htmlcomponents.Navbar() %}
|
|
<div class="container-fluid">
|
|
<a href="https://docs.victoriametrics.com/victoriametrics/relabeling/" target="_blank">Relabeling docs</a>{% space %}
|
|
|
|
{% if targetURL != "" %}
|
|
<a href="metric-relabel-debug{% if targetID != "" %}?id={%s targetID %}{% endif %}">Metric relabel debug</a>
|
|
{% else %}
|
|
<a href="target-relabel-debug{% if targetID != "" %}?id={%s targetID %}{% endif %}">Target relabel debug</a>
|
|
{% endif %}
|
|
|
|
<br>
|
|
{% if err != nil %}
|
|
{%= htmlcomponents.ErrorNotification(err) %}
|
|
{% endif %}
|
|
|
|
<div class="m-3">
|
|
<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</button>
|
|
{% endif %}
|
|
</form>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<main class="col-12">
|
|
{%= relabelDebugSteps(dss, targetURL, targetID) %}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
{% endfunc %}
|
|
|
|
{% func relabelDebugFormInputs(metric, relabelConfigs string) %}
|
|
<div>
|
|
Relabel configs:<br/>
|
|
<textarea name="relabel_configs" style="width: 100%; height: 15em; font-family: monospace" class="m-1">{%s relabelConfigs %}</textarea>
|
|
</div>
|
|
|
|
<div>
|
|
Labels:<br/>
|
|
<textarea name="metric" style="width: 100%; height: 5em; font-family: monospace" class="m-1">{%s metric %}</textarea>
|
|
</div>
|
|
{% endfunc %}
|
|
|
|
{% func relabelDebugSteps(dss []DebugStep, targetURL, targetID string) %}
|
|
{% if len(dss) > 0 %}
|
|
<div class="m-3">
|
|
<b>Original labels:</b> <samp>{%= mustFormatLabels(dss[0].In) %}</samp>
|
|
</div>
|
|
{% endif %}
|
|
<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>
|
|
{% for i, ds := range dss %}
|
|
{% code
|
|
inLabels, inErr := promutil.NewLabelsFromString(ds.In)
|
|
outLabels, outErr := promutil.NewLabelsFromString(ds.Out)
|
|
changedLabels := getChangedLabelNames(inLabels, outLabels)
|
|
%}
|
|
<tr>
|
|
<td>{%d i %}</td>
|
|
<td><b><pre class="m-2">{%s ds.Rule %}</pre></b></td>
|
|
<td>
|
|
{% if inErr == nil %}
|
|
<div class="m-2" style="font-size: 0.9em" title="deleted and updated labels highlighted in red">
|
|
{%= labelsWithHighlight(inLabels, changedLabels, "#D15757") %}
|
|
</div>
|
|
{% else %}
|
|
<div class="m-2" style="font-size: 0.9em; color: red" title="error parsing input labels">
|
|
<pre>{%s inErr.Error() %}</pre>
|
|
</div>
|
|
{% break %}
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if outErr == nil %}
|
|
<div class="m-2" style="font-size: 0.9em" title="added and updated labels highlighted in blue">
|
|
{%= labelsWithHighlight(outLabels, changedLabels, "#4495e0") %}
|
|
</div>
|
|
{% else %}
|
|
<div class="m-2" style="font-size: 0.9em; color: red" title="error parsing output labels">
|
|
<pre>{%s outErr.Error() %}</pre>
|
|
</div>
|
|
{% break %}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% if len(dss) > 0 %}
|
|
<div class="m-3">
|
|
<b>Resulting labels:</b> <samp>{%= mustFormatLabels(dss[len(dss)-1].Out) %}</samp>
|
|
{% if targetURL != "" %}
|
|
<div>
|
|
<b>Target URL:</b>{% space %}<a href="{%s targetURL %}" target="_blank">{%s targetURL %}</a>
|
|
{% if targetID != "" %}
|
|
{% space %}
|
|
(<a href="target_response?id={%s targetID %}" target="_blank" title="click to fetch target response on behalf of the scraper">response</a>)
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% endfunc %}
|
|
|
|
{% func RelabelDebugStepsJSON(targetURL, targetID string, dss []DebugStep, metric, relabelConfigs string, err error) %}
|
|
{
|
|
{% if err != nil %}
|
|
"status": "error",
|
|
"error": {%q= fmt.Sprintf("Error: %s", err) %}
|
|
{% else %}
|
|
{% code var hasError bool %}
|
|
"status": "success",
|
|
"steps": [
|
|
{% for i, ds := range dss %}
|
|
{% code
|
|
inLabels, inErr := promutil.NewLabelsFromString(ds.In)
|
|
outLabels, outErr := promutil.NewLabelsFromString(ds.Out)
|
|
changedLabels := getChangedLabelNames(inLabels, outLabels)
|
|
%}
|
|
{
|
|
"inLabels": {%q= labelsWithHighlight(inLabels, changedLabels, "#D15757") %},
|
|
"outLabels": {%q= labelsWithHighlight(outLabels, changedLabels, "#4495e0") %},
|
|
"rule": {%q= ds.Rule %},
|
|
"errors": {
|
|
{% if inErr != nil %}
|
|
"inLabels": {%q= `<span style="color: #D15757">`+inErr.Error()+`</span>` %}{% if outErr != nil %},{% endif %}
|
|
{%code hasError = true %}
|
|
{% else %}
|
|
{% endif %}
|
|
{% if outErr != nil %}
|
|
"outLabels": {%q= `<span style="color: #D15757">`+outErr.Error()+`</span>` %}
|
|
{%code hasError = true %}
|
|
{% endif %}
|
|
}
|
|
}
|
|
{% if i != len(dss)-1 %},{% endif %}
|
|
{% endfor %}
|
|
]
|
|
{% if len(dss) > 0 && !hasError %}
|
|
,
|
|
"originalLabels": {%q= mustFormatLabels(dss[0].In) %},
|
|
"resultingLabels": {%q= mustFormatLabels(dss[len(dss)-1].Out) %}
|
|
{% endif %}
|
|
{% endif %}
|
|
}
|
|
{% endfunc %}
|
|
|
|
{% func labelsWithHighlight(labels *promutil.Labels, highlight map[string]struct{}, color string) %}
|
|
{% code
|
|
labelsList := labels.GetLabels()
|
|
metricName := ""
|
|
for i, label := range labelsList {
|
|
if label.Name == "__name__" {
|
|
metricName = label.Value
|
|
labelsList = append(labelsList[:i], labelsList[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
%}
|
|
{% if metricName != "" %}
|
|
{% if _, ok := highlight["__name__"]; ok %}
|
|
<span style="font-weight:bold;color:{%s color %}">{%s metricName %}</span>
|
|
{% else %}
|
|
{%s metricName %}
|
|
{% endif %}
|
|
{% if len(labelsList) == 0 %}{% return %}{% endif %}
|
|
{% endif %}
|
|
{
|
|
{% for i, label := range labelsList %}
|
|
{% if _, ok := highlight[label.Name]; ok %}
|
|
<span style="font-weight:bold;color:{%s color %}">{%s label.Name %}={%q label.Value %}</span>
|
|
{% else %}
|
|
{%s label.Name %}={%q label.Value %}
|
|
{% endif %}
|
|
{% if i < len(labelsList)-1 %},{% space %}{% endif %}
|
|
{% endfor %}
|
|
}
|
|
{% endfunc %}
|
|
|
|
{% func mustFormatLabels(s string) %}
|
|
{% code labels, err := promutil.NewLabelsFromString(s) %}
|
|
{% if err != nil %}
|
|
<span style="color: red" title="error parsing labels: {%s err.Error() %}">{%s "error parsing labels: " + err.Error() %}</span>
|
|
{% else %}
|
|
{%= labelsWithHighlight(labels, nil, "") %}
|
|
{% endif %}
|
|
{% endfunc %}
|
|
|
|
{% endstripspace %}
|