fix(7832): added filters in inspect metrics api (#7833)

* fix(7842): added filters in inspect metrics api

* fix(metrics-explorer): added check for 40 time series only
This commit is contained in:
aniketio-ctrl 2025-05-06 12:36:12 +05:30 committed by GitHub
parent 76ed58c481
commit 6e0b50dd60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 13 deletions

View File

@ -5113,7 +5113,14 @@ WHERE metric_name = ?;`, signozMetricDBName, signozTSTableNameV41Week)
return timeSeriesCount, nil return timeSeriesCount, nil
} }
func (r *ClickHouseReader) GetAttributesForMetricName(ctx context.Context, metricName string, start, end *int64) (*[]metrics_explorer.Attribute, *model.ApiError) { func (r *ClickHouseReader) GetAttributesForMetricName(ctx context.Context, metricName string, start, end *int64, filters *v3.FilterSet) (*[]metrics_explorer.Attribute, *model.ApiError) {
whereClause := ""
if filters != nil {
conditions, _ := utils.BuildFilterConditions(filters, "t")
if conditions != nil {
whereClause = "AND " + strings.Join(conditions, " AND ")
}
}
const baseQueryTemplate = ` const baseQueryTemplate = `
SELECT SELECT
kv.1 AS key, kv.1 AS key,
@ -5121,7 +5128,7 @@ SELECT
length(groupUniqArray(10000)(kv.2)) AS valueCount length(groupUniqArray(10000)(kv.2)) AS valueCount
FROM %s.%s FROM %s.%s
ARRAY JOIN arrayFilter(x -> NOT startsWith(x.1, '__'), JSONExtractKeysAndValuesRaw(labels)) AS kv ARRAY JOIN arrayFilter(x -> NOT startsWith(x.1, '__'), JSONExtractKeysAndValuesRaw(labels)) AS kv
WHERE metric_name = ? AND __normalized=true` WHERE metric_name = ? AND __normalized=true %s`
var args []interface{} var args []interface{}
args = append(args, metricName) args = append(args, metricName)
@ -5135,7 +5142,7 @@ WHERE metric_name = ? AND __normalized=true`
tableName = signozTSTableNameV41Week tableName = signozTSTableNameV41Week
} }
query := fmt.Sprintf(baseQueryTemplate, signozMetricDBName, tableName) query := fmt.Sprintf(baseQueryTemplate, signozMetricDBName, tableName, whereClause)
if start != nil && end != nil { if start != nil && end != nil {
query += " AND unix_milli BETWEEN ? AND ?" query += " AND unix_milli BETWEEN ? AND ?"
@ -5958,6 +5965,13 @@ func (r *ClickHouseReader) GetInspectMetricsFingerprints(ctx context.Context, at
jsonExtracts = append(jsonExtracts, fmt.Sprintf("JSONExtractString(labels, '%s') AS %s", attr, keyAlias)) jsonExtracts = append(jsonExtracts, fmt.Sprintf("JSONExtractString(labels, '%s') AS %s", attr, keyAlias))
groupBys = append(groupBys, keyAlias) groupBys = append(groupBys, keyAlias)
} }
conditions, _ := utils.BuildFilterConditions(&req.Filters, "")
whereClause := ""
if len(conditions) > 0 {
whereClause = "AND " + strings.Join(conditions, " AND ")
}
start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End) start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End)
query := fmt.Sprintf(` query := fmt.Sprintf(`
SELECT SELECT
@ -5970,12 +5984,14 @@ FROM
FROM %s.%s FROM %s.%s
WHERE metric_name = ? WHERE metric_name = ?
AND unix_milli BETWEEN ? AND ? AND unix_milli BETWEEN ? AND ?
%s
) )
GROUP BY %s GROUP BY %s
ORDER BY length(fingerprints) DESC, rand() ORDER BY length(fingerprints) DESC, rand()
LIMIT 40`, // added rand to get diff value every time we run this query LIMIT 40`, // added rand to get diff value every time we run this query
strings.Join(jsonExtracts, ", "), strings.Join(jsonExtracts, ", "),
signozMetricDBName, tsTable, signozMetricDBName, tsTable,
whereClause,
strings.Join(groupBys, ", ")) strings.Join(groupBys, ", "))
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
rows, err := r.db.Query(valueCtx, query, rows, err := r.db.Query(valueCtx, query,
@ -5991,20 +6007,26 @@ LIMIT 40`, // added rand to get diff value every time we run this query
var fingerprints []string var fingerprints []string
for rows.Next() { for rows.Next() {
// Create dynamic scanning based on number of attributes // Create dynamic scanning based on number of attributes
var fingerprintsList []string var batch []string
if err := rows.Scan(&fingerprintsList); err != nil { if err := rows.Scan(&batch); err != nil {
return nil, &model.ApiError{Typ: model.ErrorExec, Err: err} return nil, &model.ApiError{Typ: model.ErrorExec, Err: err}
} }
if len(fingerprints) == 0 || len(fingerprints)+len(fingerprintsList) < 40 { remaining := 40 - len(fingerprints)
fingerprints = append(fingerprints, fingerprintsList...) if remaining <= 0 {
}
if len(fingerprints) > 40 {
break break
} }
// if this batch would overshoot, only take as many as we need
if len(batch) > remaining {
fingerprints = append(fingerprints, batch[:remaining]...)
break
}
// otherwise take the whole batch and keep going
fingerprints = append(fingerprints, batch...)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {

View File

@ -147,7 +147,7 @@ func (receiver *SummaryService) GetMetricsSummary(ctx context.Context, orgID val
}) })
g.Go(func() error { g.Go(func() error {
attributes, err := receiver.reader.GetAttributesForMetricName(ctx, metricName, nil, nil) attributes, err := receiver.reader.GetAttributesForMetricName(ctx, metricName, nil, nil, nil)
if err != nil { if err != nil {
return err return err
} }
@ -475,7 +475,7 @@ func (receiver *SummaryService) GetInspectMetrics(ctx context.Context, params *m
// Run the two queries concurrently using the derived context. // Run the two queries concurrently using the derived context.
g.Go(func() error { g.Go(func() error {
attrs, apiErr := receiver.reader.GetAttributesForMetricName(egCtx, params.MetricName, &params.Start, &params.End) attrs, apiErr := receiver.reader.GetAttributesForMetricName(egCtx, params.MetricName, &params.Start, &params.End, &params.Filters)
if apiErr != nil { if apiErr != nil {
return apiErr return apiErr
} }

View File

@ -122,7 +122,7 @@ type Reader interface {
GetMetricsLastReceived(ctx context.Context, metricName string) (int64, *model.ApiError) GetMetricsLastReceived(ctx context.Context, metricName string) (int64, *model.ApiError)
GetTotalTimeSeriesForMetricName(ctx context.Context, metricName string) (uint64, *model.ApiError) GetTotalTimeSeriesForMetricName(ctx context.Context, metricName string) (uint64, *model.ApiError)
GetActiveTimeSeriesForMetricName(ctx context.Context, metricName string, duration time.Duration) (uint64, *model.ApiError) GetActiveTimeSeriesForMetricName(ctx context.Context, metricName string, duration time.Duration) (uint64, *model.ApiError)
GetAttributesForMetricName(ctx context.Context, metricName string, start, end *int64) (*[]metrics_explorer.Attribute, *model.ApiError) GetAttributesForMetricName(ctx context.Context, metricName string, start, end *int64, set *v3.FilterSet) (*[]metrics_explorer.Attribute, *model.ApiError)
ListSummaryMetrics(ctx context.Context, orgID valuer.UUID, req *metrics_explorer.SummaryListMetricsRequest) (*metrics_explorer.SummaryListMetricsResponse, *model.ApiError) ListSummaryMetrics(ctx context.Context, orgID valuer.UUID, req *metrics_explorer.SummaryListMetricsRequest) (*metrics_explorer.SummaryListMetricsResponse, *model.ApiError)