diff --git a/pkg/query-service/app/dashboards/model.go b/pkg/query-service/app/dashboards/model.go index 989d266b51..21d39fcbe4 100644 --- a/pkg/query-service/app/dashboards/model.go +++ b/pkg/query-service/app/dashboards/model.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "regexp" + "slices" "strings" "time" @@ -453,7 +454,6 @@ func GetDashboardsInfo(ctx context.Context) (*model.DashboardsInfo, error) { totalDashboardsWithPanelAndName := 0 var dashboardNames []string count := 0 - logChQueriesCount := 0 for _, dashboard := range dashboardsData { if isDashboardWithPanelAndName(dashboard.Data) { totalDashboardsWithPanelAndName = totalDashboardsWithPanelAndName + 1 @@ -466,19 +466,18 @@ func GetDashboardsInfo(ctx context.Context) (*model.DashboardsInfo, error) { dashboardsInfo.LogsBasedPanels += dashboardInfo.LogsBasedPanels dashboardsInfo.TracesBasedPanels += dashboardInfo.TracesBasedPanels dashboardsInfo.MetricBasedPanels += dashboardsInfo.MetricBasedPanels + dashboardsInfo.LogsPanelsWithAttrContainsOp += dashboardInfo.LogsPanelsWithAttrContainsOp + dashboardsInfo.DashboardsWithLogsChQuery += dashboardInfo.DashboardsWithLogsChQuery if isDashboardWithTSV2(dashboard.Data) { count = count + 1 } - if isDashboardWithLogsClickhouseQuery(dashboard.Data) { - logChQueriesCount = logChQueriesCount + 1 - } + // check if dashboard is a has a log operator with contains } dashboardsInfo.DashboardNames = dashboardNames dashboardsInfo.TotalDashboards = len(dashboardsData) dashboardsInfo.TotalDashboardsWithPanelAndName = totalDashboardsWithPanelAndName dashboardsInfo.QueriesWithTSV2 = count - dashboardsInfo.DashboardsWithLogsChQuery = logChQueriesCount return &dashboardsInfo, nil } @@ -495,8 +494,8 @@ func isDashboardWithLogsClickhouseQuery(data map[string]interface{}) bool { if err != nil { return false } - result := strings.Contains(string(jsonData), "signoz_logs.distributed_logs ") || - strings.Contains(string(jsonData), "signoz_logs.logs ") + result := strings.Contains(string(jsonData), "signoz_logs.distributed_logs") || + strings.Contains(string(jsonData), "signoz_logs.logs") return result } @@ -532,11 +531,38 @@ func extractDashboardName(data map[string]interface{}) string { return "" } -func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo { - var logsPanelCount, tracesPanelCount, metricsPanelCount int +func checkLogPanelAttrContains(data map[string]interface{}) int { + var logsPanelsWithAttrContains int + filters, ok := data["filters"].(map[string]interface{}) + if ok && filters["items"] != nil { + items, ok := filters["items"].([]interface{}) + if ok { + for _, item := range items { + itemMap, ok := item.(map[string]interface{}) + if ok { + opStr, ok := itemMap["op"].(string) + if ok { + if slices.Contains([]string{"contains", "ncontains", "like", "nlike"}, opStr) { + // check if it's not body + key, ok := itemMap["key"].(map[string]string) + if ok && key["key"] != "body" { + logsPanelsWithAttrContains++ + } + } + } + } + } + } + } + return logsPanelsWithAttrContains +} + +func countPanelsInDashboard(inputData map[string]interface{}) model.DashboardsInfo { + var logsPanelCount, tracesPanelCount, metricsPanelCount, logsPanelsWithAttrContains int + var logChQuery bool // totalPanels := 0 - if data != nil && data["widgets"] != nil { - widgets, ok := data["widgets"] + if inputData != nil && inputData["widgets"] != nil { + widgets, ok := inputData["widgets"] if ok { data, ok := widgets.([]interface{}) if ok { @@ -559,20 +585,33 @@ func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo { metricsPanelCount++ } else if data["dataSource"] == "logs" { logsPanelCount++ + logsPanelsWithAttrContains += checkLogPanelAttrContains(data) } } } } } + } else if ok && query["queryType"] == "clickhouse_sql" && query["clickhouse_sql"] != nil { + if isDashboardWithLogsClickhouseQuery(inputData) { + logChQuery = true + } } } } } } } + + logChQueryCount := 0 + if logChQuery { + logChQueryCount = 1 + } return model.DashboardsInfo{ LogsBasedPanels: logsPanelCount, TracesBasedPanels: tracesPanelCount, MetricBasedPanels: metricsPanelCount, + + DashboardsWithLogsChQuery: logChQueryCount, + LogsPanelsWithAttrContainsOp: logsPanelsWithAttrContains, } } diff --git a/pkg/query-service/app/explorer/db.go b/pkg/query-service/app/explorer/db.go index 140b0b48d8..c53345e65b 100644 --- a/pkg/query-service/app/explorer/db.go +++ b/pkg/query-service/app/explorer/db.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "slices" "strings" "time" @@ -247,6 +248,18 @@ func GetSavedViewsInfo(ctx context.Context) (*model.SavedViewsInfo, error) { savedViewsInfo.TracesSavedViews += 1 } else if view.SourcePage == "logs" { savedViewsInfo.LogsSavedViews += 1 + + for _, query := range view.CompositeQuery.BuilderQueries { + if query.Filters != nil { + for _, item := range query.Filters.Items { + if slices.Contains([]string{"contains", "ncontains", "like", "nlike"}, string(item.Operator)) { + if item.Key.Key != "body" { + savedViewsInfo.LogsSavedViewWithContainsOp += 1 + } + } + } + } + } } } return &savedViewsInfo, nil diff --git a/pkg/query-service/model/response.go b/pkg/query-service/model/response.go index 03e538879c..3a720aed5e 100644 --- a/pkg/query-service/model/response.go +++ b/pkg/query-service/model/response.go @@ -632,12 +632,15 @@ type AlertsInfo struct { AlertNames []string `json:"alertNames"` AlertsWithTSV2 int `json:"alertsWithTSv2"` AlertsWithLogsChQuery int `json:"alertsWithLogsChQuery"` + AlertsWithLogsContainsOp int `json:"alertsWithLogsContainsOp"` } type SavedViewsInfo struct { TotalSavedViews int `json:"totalSavedViews"` TracesSavedViews int `json:"tracesSavedViews"` LogsSavedViews int `json:"logsSavedViews"` + + LogsSavedViewWithContainsOp int `json:"logsSavedViewWithContainsOp"` } type DashboardsInfo struct { @@ -649,6 +652,7 @@ type DashboardsInfo struct { DashboardNames []string `json:"dashboardNames"` QueriesWithTSV2 int `json:"queriesWithTSV2"` DashboardsWithLogsChQuery int `json:"dashboardsWithLogsChQuery"` + LogsPanelsWithAttrContainsOp int `json:"logsPanelsWithAttrContainsOp"` } type TagTelemetryData struct { diff --git a/pkg/query-service/rules/db.go b/pkg/query-service/rules/db.go index e6f8d6301c..697ea63f92 100644 --- a/pkg/query-service/rules/db.go +++ b/pkg/query-service/rules/db.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "slices" "strconv" "strings" "time" @@ -551,10 +552,6 @@ func (r *ruleDB) GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error) { if strings.Contains(alert, "time_series_v2") { alertsInfo.AlertsWithTSV2 = alertsInfo.AlertsWithTSV2 + 1 } - if strings.Contains(alert, "signoz_logs.distributed_logs") || - strings.Contains(alert, "signoz_logs.logs") { - alertsInfo.AlertsWithLogsChQuery = alertsInfo.AlertsWithLogsChQuery + 1 - } err = json.Unmarshal([]byte(alert), &rule) if err != nil { zap.L().Error("invalid rule data", zap.Error(err)) @@ -563,6 +560,29 @@ func (r *ruleDB) GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error) { alertNames = append(alertNames, rule.AlertName) if rule.AlertType == AlertTypeLogs { alertsInfo.LogsBasedAlerts = alertsInfo.LogsBasedAlerts + 1 + + if rule.RuleCondition != nil && rule.RuleCondition.CompositeQuery != nil { + if rule.RuleCondition.CompositeQuery.QueryType == v3.QueryTypeClickHouseSQL { + if strings.Contains(alert, "signoz_logs.distributed_logs") || + strings.Contains(alert, "signoz_logs.logs") { + alertsInfo.AlertsWithLogsChQuery = alertsInfo.AlertsWithLogsChQuery + 1 + } + } + } + + for _, query := range rule.RuleCondition.CompositeQuery.BuilderQueries { + if rule.RuleCondition.CompositeQuery.QueryType == v3.QueryTypeBuilder { + if query.Filters != nil { + for _, item := range query.Filters.Items { + if slices.Contains([]string{"contains", "ncontains", "like", "nlike"}, string(item.Operator)) { + if item.Key.Key != "body" { + alertsInfo.AlertsWithLogsContainsOp += 1 + } + } + } + } + } + } } else if rule.AlertType == AlertTypeMetric { alertsInfo.MetricBasedAlerts = alertsInfo.MetricBasedAlerts + 1 if rule.RuleCondition != nil && rule.RuleCondition.CompositeQuery != nil { diff --git a/pkg/query-service/telemetry/telemetry.go b/pkg/query-service/telemetry/telemetry.go index be6ad4719c..62ff020281 100644 --- a/pkg/query-service/telemetry/telemetry.go +++ b/pkg/query-service/telemetry/telemetry.go @@ -333,6 +333,7 @@ func createTelemetry() { "dashboardNames": dashboardsInfo.DashboardNames, "alertNames": alertsInfo.AlertNames, "logsBasedPanels": dashboardsInfo.LogsBasedPanels, + "logsPanelsWithAttrContains": dashboardsInfo.LogsPanelsWithAttrContainsOp, "metricBasedPanels": dashboardsInfo.MetricBasedPanels, "tracesBasedPanels": dashboardsInfo.TracesBasedPanels, "dashboardsWithTSV2": dashboardsInfo.QueriesWithTSV2, @@ -346,6 +347,7 @@ func createTelemetry() { "totalSavedViews": savedViewsInfo.TotalSavedViews, "logsSavedViews": savedViewsInfo.LogsSavedViews, "tracesSavedViews": savedViewsInfo.TracesSavedViews, + "logSavedViewsWithContainsOp": savedViewsInfo.LogsSavedViewWithContainsOp, "slackChannels": alertsInfo.SlackChannels, "webHookChannels": alertsInfo.WebHookChannels, "pagerDutyChannels": alertsInfo.PagerDutyChannels, @@ -357,6 +359,7 @@ func createTelemetry() { "metricsPrometheusQueries": alertsInfo.MetricsPrometheusQueries, "spanMetricsPrometheusQueries": alertsInfo.SpanMetricsPrometheusQueries, "alertsWithLogsChQuery": alertsInfo.AlertsWithLogsChQuery, + "alertsWithLogsContainsOp": alertsInfo.AlertsWithLogsContainsOp, } // send event only if there are dashboards or alerts or channels if (dashboardsInfo.TotalDashboards > 0 || alertsInfo.TotalAlerts > 0 || alertsInfo.TotalChannels > 0 || savedViewsInfo.TotalSavedViews > 0) && apiErr == nil {