vmalert: add filter by group or rule name to UI (#5791)

Co-authored-by: Yury Molodov <yurymolodov@gmail.com>
This commit is contained in:
Victor Amorim dos Santos 2024-02-20 08:31:41 -03:00 committed by GitHub
parent 524c0a2e07
commit b60dcbe11f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 696 additions and 581 deletions

View File

@ -1,8 +1,10 @@
function expandAll() {
$(".group-heading").show()
$('.collapse').addClass('show');
}
function collapseAll() {
$(".group-heading").show()
$('.collapse').removeClass('show');
}
@ -15,6 +17,87 @@ function toggleByID(id) {
}
}
function debounce(func, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
$('#filter').on("keyup", debounce(filter, 500));
function filter(){
$(".rule-table").removeClass('show');
$(".rule").show();
if($("#filter").val().length === 0){
$(".group-heading").show()
return
}
$(".group-heading").hide()
filterRuleByName();
filterRuleByLabels();
filterGroupsByName();
}
function filterGroupsByName(){
$( ".group-heading" ).each(function() {
const groupName = $(this).attr('data-group-name');
const filter = $("#filter").val()
const hasValue = groupName.indexOf(filter) >= 0
if (hasValue){
const target = $(this).attr("data-bs-target");
$(this).show();
$(`div[id="${target}"] .rule`).show();
}
});
}
function filterRuleByName(){
$( ".rule" ).each(function() {
const ruleName = $(this).attr("data-rule-name");
const filter = $("#filter").val()
const hasValue = ruleName.indexOf(filter) >= 0
if (hasValue){
const target = $(this).attr('data-bs-target')
$(`#rules-${target}`).addClass('show');
$(`div[data-bs-target='rules-${target}']`).show();
$(this).show();
}else{
$(this).hide();
}
});
}
function filterRuleByLabels(){
$( ".rule" ).each(function() {
const filter = $("#filter").val()
const matches = $( ".label", this ).filter(function() {
const label = $(this).text();
const hasValue = label.indexOf(filter) >= 0
return hasValue;
}).length;
if (matches > 0){
const target = $(this).attr('data-bs-target')
$(`#rules-${target}`).addClass('show');
$(`div[data-bs-target='rules-${target}']`).show();
$(this).show();
}
});
}
$(document).ready(function () {
$(".group-heading a").click(function (e) {
e.stopPropagation(); // prevent collapse logic on link click

View File

@ -70,15 +70,25 @@ btn-primary
}
}
%}
<a class="btn {%= buttonActive(filter, "") %}" role="button" onclick="window.location = window.location.pathname">All</a>
<a class="btn btn-primary" role="button" onclick="collapseAll()">Collapse All</a>
<a class="btn btn-primary" role="button" onclick="expandAll()">Expand All</a>
<a class="btn {%= buttonActive(filter, "unhealthy") %}" role="button" onclick="location.href='?filter=unhealthy'" title="Show only rules with errors">Unhealthy</a>
<a class="btn {%= buttonActive(filter, "noMatch") %}" role="button" onclick="location.href='?filter=noMatch'" title="Show only rules matching no time series during last evaluation">NoMatch</a>
<a class="btn {%= buttonActive(filter, "") %}" role="button" onclick="window.location = window.location.pathname">All</a>
<a class="btn btn-primary" role="button" onclick="collapseAll()">Collapse All</a>
<a class="btn btn-primary" role="button" onclick="expandAll()">Expand All</a>
<a class="btn {%= buttonActive(filter, "unhealthy") %}" role="button" onclick="location.href='?filter=unhealthy'" title="Show only rules with errors">Unhealthy</a>
<a class="btn {%= buttonActive(filter, "noMatch") %}" role="button" onclick="location.href='?filter=noMatch'" title="Show only rules matching no time series during last evaluation">NoMatch</a>
<div class="pt-2 col-md-4 col-lg-4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<svg fill="#000000" height="25px" width="20px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 490.4 490.4" xml:space="preserve"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <path d="M484.1,454.796l-110.5-110.6c29.8-36.3,47.6-82.8,47.6-133.4c0-116.3-94.3-210.6-210.6-210.6S0,94.496,0,210.796 s94.3,210.6,210.6,210.6c50.8,0,97.4-18,133.8-48l110.5,110.5c12.9,11.8,25,4.2,29.2,0C492.5,475.596,492.5,463.096,484.1,454.796z M41.1,210.796c0-93.6,75.9-169.5,169.5-169.5s169.6,75.9,169.6,169.5s-75.9,169.5-169.5,169.5S41.1,304.396,41.1,210.796z"></path> </g> </g></svg>
</span>
</div>
<input id="filter" placeholder="Filter by group, rule or labels" type="text" class="form-control"/>
</div>
</div>
{% if len(groups) > 0 %}
{% for _, g := range groups %}
<div
class="group-heading{% if rNotOk[g.ID] > 0 %} alert-danger{%endif%}" data-bs-target="rules-{%s g.ID %}">
class="group-heading{% if rNotOk[g.ID] > 0 %} alert-danger{%endif%}" data-bs-target="rules-{%s g.ID %}" data-group-name="{%s g.Name %}">
<span class="anchor" id="group-{%s g.ID %}"></span>
<a href="#group-{%s g.ID %}">{%s g.Name %}{% if g.Type != "prometheus" %} ({%s g.Type %}){% endif %} (every {%f.0 g.Interval %}s) #</a>
{% if rNotOk[g.ID] > 0 %}<span class="badge bg-danger" title="Number of rules with status Error">{%d rNotOk[g.ID] %}</span> {% endif %}
@ -100,7 +110,7 @@ btn-primary
</div>
{% endif %}
</div>
<div class="collapse" id="rules-{%s g.ID %}">
<div class="collapse rule-table" id="rules-{%s g.ID %}">
<table class="table table-striped table-hover table-sm">
<thead>
<tr>
@ -111,7 +121,7 @@ btn-primary
</thead>
<tbody>
{% for _, r := range g.Rules %}
<tr{% if r.LastError != "" %} class="alert-danger"{% endif %}>
<tr class="rule{% if r.LastError != "" %} alert-danger{% endif %}" data-rule-name="{%s r.Name %}" data-bs-target="{%s g.ID %}">
<td>
<div class="row">
<div class="col-12 mb-2">
@ -134,7 +144,7 @@ btn-primary
<div class="col-12 mb-2">
{% if len(r.Labels) > 0 %} <b>Labels:</b>{% endif %}
{% for k, v := range r.Labels %}
<span class="ms-1 badge bg-primary">{%s k %}={%s v %}</span>
<span class="ms-1 badge bg-primary label">{%s k %}={%s v %}</span>
{% endfor %}
</div>
{% if r.LastError != "" %}

File diff suppressed because it is too large Load Diff