mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 02:09:04 +08:00
chore: add total count and state filter (#5745)
This commit is contained in:
parent
d7fd1d032b
commit
b798518aa9
@ -5223,7 +5223,7 @@ func (r *ClickHouseReader) AddRuleStateHistory(ctx context.Context, ruleStateHis
|
||||
}
|
||||
|
||||
func (r *ClickHouseReader) ReadRuleStateHistoryByRuleID(
|
||||
ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) ([]v3.RuleStateHistory, error) {
|
||||
ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) (*v3.RuleStateTimeline, error) {
|
||||
|
||||
var conditions []string
|
||||
|
||||
@ -5231,6 +5231,10 @@ func (r *ClickHouseReader) ReadRuleStateHistoryByRuleID(
|
||||
|
||||
conditions = append(conditions, fmt.Sprintf("unix_milli >= %d AND unix_milli < %d", params.Start, params.End))
|
||||
|
||||
if params.State != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("state = '%s'", params.State))
|
||||
}
|
||||
|
||||
if params.Filters != nil && len(params.Filters.Items) != 0 {
|
||||
for _, item := range params.Filters.Items {
|
||||
toFormat := item.Value
|
||||
@ -5289,7 +5293,19 @@ func (r *ClickHouseReader) ReadRuleStateHistoryByRuleID(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return history, nil
|
||||
var total uint64
|
||||
err = r.db.QueryRow(ctx, fmt.Sprintf("SELECT count(*) FROM %s.%s WHERE %s",
|
||||
signozHistoryDBName, ruleStateHistoryTableName, whereClause)).Scan(&total)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
timeline := &v3.RuleStateTimeline{
|
||||
Items: history,
|
||||
Total: total,
|
||||
}
|
||||
|
||||
return timeline, nil
|
||||
}
|
||||
|
||||
func (r *ClickHouseReader) ReadRuleStateHistoryTopContributorsByRuleID(
|
||||
|
@ -716,6 +716,13 @@ func (aH *APIHandler) getRuleStats(w http.ResponseWriter, r *http.Request) {
|
||||
RespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: err}, nil)
|
||||
return
|
||||
}
|
||||
if math.IsNaN(currentAvgResolutionTime) || math.IsInf(currentAvgResolutionTime, 0) {
|
||||
currentAvgResolutionTime = 0
|
||||
}
|
||||
if math.IsNaN(pastAvgResolutionTime) || math.IsInf(pastAvgResolutionTime, 0) {
|
||||
pastAvgResolutionTime = 0
|
||||
}
|
||||
|
||||
stats := v3.Stats{
|
||||
TotalCurrentTriggers: totalCurrentTriggers,
|
||||
TotalPastTriggers: totalPastTriggers,
|
||||
@ -788,6 +795,37 @@ func (aH *APIHandler) getRuleStateHistory(w http.ResponseWriter, r *http.Request
|
||||
RespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: err}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := aH.ruleManager.GetRule(r.Context(), ruleID)
|
||||
if err == nil {
|
||||
for idx := range res.Items {
|
||||
lbls := make(map[string]string)
|
||||
err := json.Unmarshal([]byte(res.Items[idx].Labels), &lbls)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
filterItems := []v3.FilterItem{}
|
||||
if rule.AlertType == "LOGS_BASED_ALERT" || rule.AlertType == "TRACES_BASED_ALERT" {
|
||||
if rule.RuleCondition.CompositeQuery != nil {
|
||||
if rule.RuleCondition.QueryType() == v3.QueryTypeBuilder {
|
||||
for _, query := range rule.RuleCondition.CompositeQuery.BuilderQueries {
|
||||
if query.Filters != nil && len(query.Filters.Items) > 0 {
|
||||
filterItems = append(filterItems, query.Filters.Items...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newFilters := common.PrepareFilters(lbls, filterItems)
|
||||
ts := time.Unix(res.Items[idx].UnixMilli/1000, 0)
|
||||
if rule.AlertType == "LOGS_BASED_ALERT" {
|
||||
res.Items[idx].RelatedLogsLink = common.PrepareLinksToLogs(ts, newFilters)
|
||||
} else if rule.AlertType == "TRACES_BASED_ALERT" {
|
||||
res.Items[idx].RelatedTracesLink = common.PrepareLinksToTraces(ts, newFilters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aH.Respond(w, res)
|
||||
}
|
||||
|
||||
@ -805,6 +843,25 @@ func (aH *APIHandler) getRuleStateHistoryTopContributors(w http.ResponseWriter,
|
||||
RespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: err}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := aH.ruleManager.GetRule(r.Context(), ruleID)
|
||||
if err == nil {
|
||||
for idx := range res {
|
||||
lbls := make(map[string]string)
|
||||
err := json.Unmarshal([]byte(res[idx].Labels), &lbls)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ts := time.Unix(params.End/1000, 0)
|
||||
filters := common.PrepareFilters(lbls, nil)
|
||||
if rule.AlertType == "LOGS_BASED_ALERT" {
|
||||
res[idx].RelatedLogsLink = common.PrepareLinksToLogs(ts, filters)
|
||||
} else if rule.AlertType == "TRACES_BASED_ALERT" {
|
||||
res[idx].RelatedTracesLink = common.PrepareLinksToTraces(ts, filters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aH.Respond(w, res)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"go.signoz.io/signoz/pkg/query-service/constants"
|
||||
@ -70,3 +73,183 @@ func LCMList(nums []int64) int64 {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO(srikanthccv): move the custom function in threshold_rule.go to here
|
||||
func PrepareLinksToTraces(ts time.Time, filterItems []v3.FilterItem) string {
|
||||
|
||||
start := ts.Add(-time.Minute * 15)
|
||||
end := ts.Add(time.Minute * 15)
|
||||
|
||||
// Traces list view expects time in nanoseconds
|
||||
tr := v3.URLShareableTimeRange{
|
||||
Start: start.UnixNano(),
|
||||
End: end.UnixNano(),
|
||||
PageSize: 100,
|
||||
}
|
||||
|
||||
options := v3.URLShareableOptions{
|
||||
MaxLines: 2,
|
||||
Format: "list",
|
||||
SelectColumns: constants.TracesListViewDefaultSelectedColumns,
|
||||
}
|
||||
|
||||
period, _ := json.Marshal(tr)
|
||||
urlEncodedTimeRange := url.QueryEscape(string(period))
|
||||
|
||||
urlData := v3.URLShareableCompositeQuery{
|
||||
QueryType: string(v3.QueryTypeBuilder),
|
||||
Builder: v3.URLShareableBuilderQuery{
|
||||
QueryData: []v3.BuilderQuery{
|
||||
{
|
||||
DataSource: v3.DataSourceTraces,
|
||||
QueryName: "A",
|
||||
AggregateOperator: v3.AggregateOperatorNoOp,
|
||||
AggregateAttribute: v3.AttributeKey{},
|
||||
Filters: &v3.FilterSet{
|
||||
Items: filterItems,
|
||||
Operator: "AND",
|
||||
},
|
||||
Expression: "A",
|
||||
Disabled: false,
|
||||
Having: []v3.Having{},
|
||||
StepInterval: 60,
|
||||
OrderBy: []v3.OrderBy{
|
||||
{
|
||||
ColumnName: "timestamp",
|
||||
Order: "desc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
QueryFormulas: make([]string, 0),
|
||||
},
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(urlData)
|
||||
compositeQuery := url.QueryEscape(string(data))
|
||||
|
||||
optionsData, _ := json.Marshal(options)
|
||||
urlEncodedOptions := url.QueryEscape(string(optionsData))
|
||||
|
||||
return fmt.Sprintf("compositeQuery=%s&timeRange=%s&startTime=%d&endTime=%d&options=%s", compositeQuery, urlEncodedTimeRange, tr.Start, tr.End, urlEncodedOptions)
|
||||
}
|
||||
|
||||
func PrepareLinksToLogs(ts time.Time, filterItems []v3.FilterItem) string {
|
||||
start := ts.Add(-time.Minute * 15)
|
||||
end := ts.Add(time.Minute * 15)
|
||||
|
||||
// Logs list view expects time in milliseconds
|
||||
// Logs list view expects time in milliseconds
|
||||
tr := v3.URLShareableTimeRange{
|
||||
Start: start.UnixMilli(),
|
||||
End: end.UnixMilli(),
|
||||
PageSize: 100,
|
||||
}
|
||||
|
||||
options := v3.URLShareableOptions{
|
||||
MaxLines: 2,
|
||||
Format: "list",
|
||||
SelectColumns: []v3.AttributeKey{},
|
||||
}
|
||||
|
||||
period, _ := json.Marshal(tr)
|
||||
urlEncodedTimeRange := url.QueryEscape(string(period))
|
||||
|
||||
urlData := v3.URLShareableCompositeQuery{
|
||||
QueryType: string(v3.QueryTypeBuilder),
|
||||
Builder: v3.URLShareableBuilderQuery{
|
||||
QueryData: []v3.BuilderQuery{
|
||||
{
|
||||
DataSource: v3.DataSourceLogs,
|
||||
QueryName: "A",
|
||||
AggregateOperator: v3.AggregateOperatorNoOp,
|
||||
AggregateAttribute: v3.AttributeKey{},
|
||||
Filters: &v3.FilterSet{
|
||||
Items: filterItems,
|
||||
Operator: "AND",
|
||||
},
|
||||
Expression: "A",
|
||||
Disabled: false,
|
||||
Having: []v3.Having{},
|
||||
StepInterval: 60,
|
||||
OrderBy: []v3.OrderBy{
|
||||
{
|
||||
ColumnName: "timestamp",
|
||||
Order: "desc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
QueryFormulas: make([]string, 0),
|
||||
},
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(urlData)
|
||||
compositeQuery := url.QueryEscape(string(data))
|
||||
|
||||
optionsData, _ := json.Marshal(options)
|
||||
urlEncodedOptions := url.QueryEscape(string(optionsData))
|
||||
|
||||
return fmt.Sprintf("compositeQuery=%s&timeRange=%s&startTime=%d&endTime=%d&options=%s", compositeQuery, urlEncodedTimeRange, tr.Start, tr.End, urlEncodedOptions)
|
||||
}
|
||||
|
||||
// The following function is used to prepare the where clause for the query
|
||||
// `lbls` contains the key value pairs of the labels from the result of the query
|
||||
// We iterate over the where clause and replace the labels with the actual values
|
||||
// There are two cases:
|
||||
// 1. The label is present in the where clause
|
||||
// 2. The label is not present in the where clause
|
||||
//
|
||||
// Example for case 2:
|
||||
// Latency by serviceName without any filter
|
||||
// In this case, for each service with latency > threshold we send a notification
|
||||
// The expectation will be that clicking on the related traces for service A, will
|
||||
// take us to the traces page with the filter serviceName=A
|
||||
// So for all the missing labels in the where clause, we add them as key = value
|
||||
//
|
||||
// Example for case 1:
|
||||
// Severity text IN (WARN, ERROR)
|
||||
// In this case, the Severity text will appear in the `lbls` if it were part of the group
|
||||
// by clause, in which case we replace it with the actual value for the notification
|
||||
// i.e Severity text = WARN
|
||||
// If the Severity text is not part of the group by clause, then we add it as it is
|
||||
func PrepareFilters(labels map[string]string, filters []v3.FilterItem) []v3.FilterItem {
|
||||
var filterItems []v3.FilterItem
|
||||
|
||||
added := make(map[string]struct{})
|
||||
|
||||
for _, item := range filters {
|
||||
exists := false
|
||||
for key, value := range labels {
|
||||
if item.Key.Key == key {
|
||||
// if the label is present in the where clause, replace it with key = value
|
||||
filterItems = append(filterItems, v3.FilterItem{
|
||||
Key: item.Key,
|
||||
Operator: v3.FilterOperatorEqual,
|
||||
Value: value,
|
||||
})
|
||||
exists = true
|
||||
added[key] = struct{}{}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !exists {
|
||||
// if the label is not present in the where clause, add it as it is
|
||||
filterItems = append(filterItems, item)
|
||||
}
|
||||
}
|
||||
|
||||
// add the labels which are not present in the where clause
|
||||
for key, value := range labels {
|
||||
if _, ok := added[key]; !ok {
|
||||
filterItems = append(filterItems, v3.FilterItem{
|
||||
Key: v3.AttributeKey{Key: key},
|
||||
Operator: v3.FilterOperatorEqual,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return filterItems
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ type Reader interface {
|
||||
|
||||
AddRuleStateHistory(ctx context.Context, ruleStateHistory []v3.RuleStateHistory) error
|
||||
GetOverallStateTransitions(ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) ([]v3.RuleStateTransition, error)
|
||||
ReadRuleStateHistoryByRuleID(ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) ([]v3.RuleStateHistory, error)
|
||||
ReadRuleStateHistoryByRuleID(ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) (*v3.RuleStateTimeline, error)
|
||||
GetTotalTriggers(ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) (uint64, error)
|
||||
GetTriggersByInterval(ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) (*v3.Series, error)
|
||||
GetAvgResolutionTime(ctx context.Context, ruleID string, params *v3.QueryRuleStateHistory) (float64, error)
|
||||
|
@ -1181,6 +1181,11 @@ func (l LabelsString) String() string {
|
||||
return string(l)
|
||||
}
|
||||
|
||||
type RuleStateTimeline struct {
|
||||
Items []RuleStateHistory `json:"items"`
|
||||
Total uint64 `json:"total"`
|
||||
}
|
||||
|
||||
type RuleStateHistory struct {
|
||||
RuleID string `json:"ruleID" ch:"rule_id"`
|
||||
RuleName string `json:"ruleName" ch:"rule_name"`
|
||||
@ -1194,11 +1199,15 @@ type RuleStateHistory struct {
|
||||
Labels LabelsString `json:"labels" ch:"labels"`
|
||||
Fingerprint uint64 `json:"fingerprint" ch:"fingerprint"`
|
||||
Value float64 `json:"value" ch:"value"`
|
||||
|
||||
RelatedTracesLink string `json:"relatedTracesLink"`
|
||||
RelatedLogsLink string `json:"relatedLogsLink"`
|
||||
}
|
||||
|
||||
type QueryRuleStateHistory struct {
|
||||
Start int64 `json:"start"`
|
||||
End int64 `json:"end"`
|
||||
State string `json:"state"`
|
||||
Filters *FilterSet `json:"filters"`
|
||||
Offset int64 `json:"offset"`
|
||||
Limit int64 `json:"limit"`
|
||||
@ -1219,9 +1228,11 @@ func (r *QueryRuleStateHistory) Validate() error {
|
||||
}
|
||||
|
||||
type RuleStateHistoryContributor struct {
|
||||
Fingerprint uint64 `json:"fingerprint" ch:"fingerprint"`
|
||||
Labels LabelsString `json:"labels" ch:"labels"`
|
||||
Count uint64 `json:"count" ch:"count"`
|
||||
Fingerprint uint64 `json:"fingerprint" ch:"fingerprint"`
|
||||
Labels LabelsString `json:"labels" ch:"labels"`
|
||||
Count uint64 `json:"count" ch:"count"`
|
||||
RelatedTracesLink string `json:"relatedTracesLink"`
|
||||
RelatedLogsLink string `json:"relatedLogsLink"`
|
||||
}
|
||||
|
||||
type RuleStateTransition struct {
|
||||
@ -1255,3 +1266,25 @@ type QueryProgress struct {
|
||||
|
||||
ElapsedMs uint64 `json:"elapsed_ms"`
|
||||
}
|
||||
|
||||
type URLShareableTimeRange struct {
|
||||
Start int64 `json:"start"`
|
||||
End int64 `json:"end"`
|
||||
PageSize int64 `json:"pageSize"`
|
||||
}
|
||||
|
||||
type URLShareableBuilderQuery struct {
|
||||
QueryData []BuilderQuery `json:"queryData"`
|
||||
QueryFormulas []string `json:"queryFormulas"`
|
||||
}
|
||||
|
||||
type URLShareableCompositeQuery struct {
|
||||
QueryType string `json:"queryType"`
|
||||
Builder URLShareableBuilderQuery `json:"builder"`
|
||||
}
|
||||
|
||||
type URLShareableOptions struct {
|
||||
MaxLines int `json:"maxLines"`
|
||||
Format string `json:"format"`
|
||||
SelectColumns []AttributeKey `json:"selectColumns"`
|
||||
}
|
||||
|
@ -67,6 +67,8 @@ type Alert struct {
|
||||
Labels labels.BaseLabels
|
||||
Annotations labels.BaseLabels
|
||||
|
||||
QueryResultLables labels.BaseLabels
|
||||
|
||||
GeneratorURL string
|
||||
|
||||
// list of preferred receivers, e.g. slack
|
||||
|
@ -242,25 +242,3 @@ type GettableRule struct {
|
||||
UpdatedAt *time.Time `json:"updateAt"`
|
||||
UpdatedBy *string `json:"updateBy"`
|
||||
}
|
||||
|
||||
type timeRange struct {
|
||||
Start int64 `json:"start"`
|
||||
End int64 `json:"end"`
|
||||
PageSize int64 `json:"pageSize"`
|
||||
}
|
||||
|
||||
type builderQuery struct {
|
||||
QueryData []v3.BuilderQuery `json:"queryData"`
|
||||
QueryFormulas []string `json:"queryFormulas"`
|
||||
}
|
||||
|
||||
type urlShareableCompositeQuery struct {
|
||||
QueryType string `json:"queryType"`
|
||||
Builder builderQuery `json:"builder"`
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
MaxLines int `json:"maxLines"`
|
||||
Format string `json:"format"`
|
||||
SelectColumns []v3.AttributeKey `json:"selectColumns"`
|
||||
}
|
||||
|
@ -411,6 +411,7 @@ func (r *PromRule) Eval(ctx context.Context, ts time.Time, queriers *Queriers) (
|
||||
}
|
||||
|
||||
lb := plabels.NewBuilder(alertSmpl.Metric).Del(plabels.MetricName)
|
||||
resultLabels := plabels.NewBuilder(alertSmpl.Metric).Del(plabels.MetricName).Labels()
|
||||
|
||||
for _, l := range r.labels {
|
||||
lb.Set(l.Name, expand(l.Value))
|
||||
@ -439,13 +440,14 @@ func (r *PromRule) Eval(ctx context.Context, ts time.Time, queriers *Queriers) (
|
||||
}
|
||||
|
||||
alerts[h] = &Alert{
|
||||
Labels: lbs,
|
||||
Annotations: annotations,
|
||||
ActiveAt: ts,
|
||||
State: StatePending,
|
||||
Value: alertSmpl.F,
|
||||
GeneratorURL: r.GeneratorURL(),
|
||||
Receivers: r.preferredChannels,
|
||||
Labels: lbs,
|
||||
QueryResultLables: resultLabels,
|
||||
Annotations: annotations,
|
||||
ActiveAt: ts,
|
||||
State: StatePending,
|
||||
Value: alertSmpl.F,
|
||||
GeneratorURL: r.GeneratorURL(),
|
||||
Receivers: r.preferredChannels,
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +491,7 @@ func (r *PromRule) Eval(ctx context.Context, ts time.Time, queriers *Queriers) (
|
||||
StateChanged: true,
|
||||
UnixMilli: ts.UnixMilli(),
|
||||
Labels: v3.LabelsString(labelsJSON),
|
||||
Fingerprint: a.Labels.Hash(),
|
||||
Fingerprint: a.QueryResultLables.Hash(),
|
||||
})
|
||||
}
|
||||
continue
|
||||
@ -509,7 +511,7 @@ func (r *PromRule) Eval(ctx context.Context, ts time.Time, queriers *Queriers) (
|
||||
StateChanged: true,
|
||||
UnixMilli: ts.UnixMilli(),
|
||||
Labels: v3.LabelsString(labelsJSON),
|
||||
Fingerprint: a.Labels.Hash(),
|
||||
Fingerprint: a.QueryResultLables.Hash(),
|
||||
Value: a.Value,
|
||||
})
|
||||
}
|
||||
|
@ -625,13 +625,13 @@ func (r *ThresholdRule) prepareLinksToLogs(ts time.Time, lbls labels.Labels) str
|
||||
|
||||
q := r.prepareQueryRange(ts)
|
||||
// Logs list view expects time in milliseconds
|
||||
tr := timeRange{
|
||||
tr := v3.URLShareableTimeRange{
|
||||
Start: q.Start,
|
||||
End: q.End,
|
||||
PageSize: 100,
|
||||
}
|
||||
|
||||
options := Options{
|
||||
options := v3.URLShareableOptions{
|
||||
MaxLines: 2,
|
||||
Format: "list",
|
||||
SelectColumns: []v3.AttributeKey{},
|
||||
@ -641,9 +641,9 @@ func (r *ThresholdRule) prepareLinksToLogs(ts time.Time, lbls labels.Labels) str
|
||||
urlEncodedTimeRange := url.QueryEscape(string(period))
|
||||
|
||||
filterItems := r.fetchFilters(selectedQuery, lbls)
|
||||
urlData := urlShareableCompositeQuery{
|
||||
urlData := v3.URLShareableCompositeQuery{
|
||||
QueryType: string(v3.QueryTypeBuilder),
|
||||
Builder: builderQuery{
|
||||
Builder: v3.URLShareableBuilderQuery{
|
||||
QueryData: []v3.BuilderQuery{
|
||||
{
|
||||
DataSource: v3.DataSourceLogs,
|
||||
@ -689,13 +689,13 @@ func (r *ThresholdRule) prepareLinksToTraces(ts time.Time, lbls labels.Labels) s
|
||||
|
||||
q := r.prepareQueryRange(ts)
|
||||
// Traces list view expects time in nanoseconds
|
||||
tr := timeRange{
|
||||
tr := v3.URLShareableTimeRange{
|
||||
Start: q.Start * time.Second.Microseconds(),
|
||||
End: q.End * time.Second.Microseconds(),
|
||||
PageSize: 100,
|
||||
}
|
||||
|
||||
options := Options{
|
||||
options := v3.URLShareableOptions{
|
||||
MaxLines: 2,
|
||||
Format: "list",
|
||||
SelectColumns: constants.TracesListViewDefaultSelectedColumns,
|
||||
@ -705,9 +705,9 @@ func (r *ThresholdRule) prepareLinksToTraces(ts time.Time, lbls labels.Labels) s
|
||||
urlEncodedTimeRange := url.QueryEscape(string(period))
|
||||
|
||||
filterItems := r.fetchFilters(selectedQuery, lbls)
|
||||
urlData := urlShareableCompositeQuery{
|
||||
urlData := v3.URLShareableCompositeQuery{
|
||||
QueryType: string(v3.QueryTypeBuilder),
|
||||
Builder: builderQuery{
|
||||
Builder: v3.URLShareableBuilderQuery{
|
||||
QueryData: []v3.BuilderQuery{
|
||||
{
|
||||
DataSource: v3.DataSourceTraces,
|
||||
@ -954,6 +954,7 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
|
||||
}
|
||||
|
||||
lb := labels.NewBuilder(smpl.Metric).Del(labels.MetricNameLabel).Del(labels.TemporalityLabel)
|
||||
resultLabels := labels.NewBuilder(smpl.MetricOrig).Del(labels.MetricNameLabel).Del(labels.TemporalityLabel).Labels()
|
||||
|
||||
for _, l := range r.labels {
|
||||
lb.Set(l.Name, expand(l.Value))
|
||||
@ -1001,14 +1002,15 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
|
||||
}
|
||||
|
||||
alerts[h] = &Alert{
|
||||
Labels: lbs,
|
||||
Annotations: annotations,
|
||||
ActiveAt: ts,
|
||||
State: StatePending,
|
||||
Value: smpl.V,
|
||||
GeneratorURL: r.GeneratorURL(),
|
||||
Receivers: r.preferredChannels,
|
||||
Missing: smpl.IsMissing,
|
||||
Labels: lbs,
|
||||
QueryResultLables: resultLabels,
|
||||
Annotations: annotations,
|
||||
ActiveAt: ts,
|
||||
State: StatePending,
|
||||
Value: smpl.V,
|
||||
GeneratorURL: r.GeneratorURL(),
|
||||
Receivers: r.preferredChannels,
|
||||
Missing: smpl.IsMissing,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1034,7 +1036,7 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
|
||||
|
||||
// Check if any pending alerts should be removed or fire now. Write out alert timeseries.
|
||||
for fp, a := range r.active {
|
||||
labelsJSON, err := json.Marshal(a.Labels)
|
||||
labelsJSON, err := json.Marshal(a.QueryResultLables)
|
||||
if err != nil {
|
||||
zap.L().Error("error marshaling labels", zap.Error(err), zap.Any("labels", a.Labels))
|
||||
}
|
||||
@ -1054,7 +1056,7 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
|
||||
StateChanged: true,
|
||||
UnixMilli: ts.UnixMilli(),
|
||||
Labels: v3.LabelsString(labelsJSON),
|
||||
Fingerprint: a.Labels.Hash(),
|
||||
Fingerprint: a.QueryResultLables.Hash(),
|
||||
})
|
||||
}
|
||||
continue
|
||||
@ -1074,7 +1076,7 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
|
||||
StateChanged: true,
|
||||
UnixMilli: ts.UnixMilli(),
|
||||
Labels: v3.LabelsString(labelsJSON),
|
||||
Fingerprint: a.Labels.Hash(),
|
||||
Fingerprint: a.QueryResultLables.Hash(),
|
||||
Value: a.Value,
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user