diff --git a/pkg/query-service/app/clickhouseReader/options.go b/pkg/query-service/app/clickhouseReader/options.go index b9de1db054..ed05e5843d 100644 --- a/pkg/query-service/app/clickhouseReader/options.go +++ b/pkg/query-service/app/clickhouseReader/options.go @@ -51,6 +51,9 @@ const ( defaultTraceLocalTableName string = "signoz_index_v3" defaultTraceResourceTableV3 string = "distributed_traces_v3_resource" defaultTraceSummaryTable string = "distributed_trace_summary" + + defaultMetadataDB string = "signoz_metadata" + defaultMetadataTable string = "distributed_attributes_metadata" ) // NamespaceConfig is Clickhouse's internal configuration data @@ -94,6 +97,9 @@ type namespaceConfig struct { TraceLocalTableNameV3 string TraceResourceTableV3 string TraceSummaryTable string + + MetadataDB string + MetadataTable string } // Connecto defines how to connect to the database @@ -192,6 +198,9 @@ func NewOptions( TraceLocalTableNameV3: defaultTraceLocalTableName, TraceResourceTableV3: defaultTraceResourceTableV3, TraceSummaryTable: defaultTraceSummaryTable, + + MetadataDB: defaultMetadataDB, + MetadataTable: defaultMetadataTable, }, others: make(map[string]*namespaceConfig, len(otherNamespaces)), } diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index 9c7828af45..0215d4d25b 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -156,6 +156,9 @@ type ClickHouseReader struct { traceLocalTableName string traceResourceTableV3 string traceSummaryTable string + + metadataDB string + metadataTable string } // NewTraceReader returns a TraceReader for the database @@ -276,6 +279,9 @@ func NewReaderFromClickhouseConnection( traceTableName: traceTableName, traceResourceTableV3: options.primary.TraceResourceTableV3, traceSummaryTable: options.primary.TraceSummaryTable, + + metadataDB: options.primary.MetadataDB, + metadataTable: options.primary.MetadataTable, } } @@ -3610,6 +3616,62 @@ func (r *ClickHouseReader) GetLogAttributeKeys(ctx context.Context, req *v3.Filt return &response, nil } +func (r *ClickHouseReader) FetchRelatedValues(ctx context.Context, req *v3.FilterAttributeValueRequest) ([]string, error) { + var conditions []string + + if len(req.SelectedAttributeValues) != 0 { + for _, item := range req.SelectedAttributeValues { + fmtVal := utils.ClickHouseFormattedValue(item.Value) + var colName string + switch item.Key.Type { + case v3.AttributeKeyTypeResource: + colName = "resource_attributes" + case v3.AttributeKeyTypeTag: + colName = "attributes" + default: + colName = "attributes" + } + conditions = append(conditions, fmt.Sprintf("mapContains(%s, '%s') AND %s['%s'] IN %s", colName, item.Key.Key, colName, item.Key.Key, fmtVal)) + } + } + whereClause := strings.Join(conditions, " OR ") + + var selectColumn string + switch req.TagType { + case v3.TagTypeResource: + selectColumn = "resource_attributes" + "['" + req.FilterAttributeKey + "']" + case v3.TagTypeTag: + selectColumn = "attributes" + "['" + req.FilterAttributeKey + "']" + default: + selectColumn = "attributes" + "['" + req.FilterAttributeKey + "']" + } + + filterSubQuery := fmt.Sprintf( + "SELECT DISTINCT %s FROM %s.%s WHERE %s", + selectColumn, + r.metadataDB, + r.metadataTable, + whereClause, + ) + + rows, err := r.db.Query(ctx, filterSubQuery) + if err != nil { + return nil, fmt.Errorf("error while executing query: %s", err.Error()) + } + defer rows.Close() + + var attributeValues []string + for rows.Next() { + var value string + if err := rows.Scan(&value); err != nil { + return nil, fmt.Errorf("error while scanning rows: %s", err.Error()) + } + attributeValues = append(attributeValues, value) + } + + return attributeValues, nil +} + func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error) { var err error var filterValueColumn string @@ -3711,6 +3773,11 @@ func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.Fi } } + relatedValues, _ := r.FetchRelatedValues(ctx, req) + attributeValues.RelatedValues = &v3.FilterAttributeValueResponse{ + StringAttributeValues: relatedValues, + } + return &attributeValues, nil } diff --git a/pkg/query-service/app/parser.go b/pkg/query-service/app/parser.go index 8cfc621662..e3dcef117c 100644 --- a/pkg/query-service/app/parser.go +++ b/pkg/query-service/app/parser.go @@ -740,7 +740,8 @@ func parseFilterAttributeValueRequest(r *http.Request) (*v3.FilterAttributeValue filterAttributeKeyDataType := v3.AttributeKeyDataType(r.URL.Query().Get("filterAttributeKeyDataType")) // can be empty aggregateAttribute := r.URL.Query().Get("aggregateAttribute") tagType := v3.TagType(r.URL.Query().Get("tagType")) // can be empty - + selectedAttributeValuesStr := r.URL.Query().Get("selectedAttributeValues") + metricNamesStr := r.URL.Query().Get("metricNames") limit, err := strconv.Atoi(r.URL.Query().Get("limit")) if err != nil { limit = 50 @@ -756,6 +757,24 @@ func parseFilterAttributeValueRequest(r *http.Request) (*v3.FilterAttributeValue } } + // parse json string to []FilterItem + var selectedAttributeValues []v3.FilterItem + if len(selectedAttributeValuesStr) > 0 { + err := json.Unmarshal([]byte(selectedAttributeValuesStr), &selectedAttributeValues) + if err != nil { + return nil, err + } + } + + // parse json string to []string + var metricNames []string + if len(metricNamesStr) > 0 { + err := json.Unmarshal([]byte(metricNamesStr), &metricNames) + if err != nil { + return nil, err + } + } + req = v3.FilterAttributeValueRequest{ DataSource: dataSource, AggregateOperator: aggregateOperator, @@ -765,6 +784,8 @@ func parseFilterAttributeValueRequest(r *http.Request) (*v3.FilterAttributeValue SearchText: r.URL.Query().Get("searchText"), FilterAttributeKey: r.URL.Query().Get("attributeKey"), FilterAttributeKeyDataType: filterAttributeKeyDataType, + SelectedAttributeValues: selectedAttributeValues, + MetricNames: metricNames, } return &req, nil } diff --git a/pkg/query-service/model/v3/v3.go b/pkg/query-service/model/v3/v3.go index 4d6a6b1ac8..1a0a9d687c 100644 --- a/pkg/query-service/model/v3/v3.go +++ b/pkg/query-service/model/v3/v3.go @@ -305,6 +305,8 @@ type FilterAttributeValueRequest struct { TagType TagType `json:"tagType"` SearchText string `json:"searchText"` Limit int `json:"limit"` + SelectedAttributeValues []FilterItem `json:"selectedAttributeValues"` + MetricNames []string `json:"metricNames"` } type AggregateAttributeResponse struct { @@ -368,6 +370,8 @@ type FilterAttributeValueResponse struct { StringAttributeValues []string `json:"stringAttributeValues"` NumberAttributeValues []interface{} `json:"numberAttributeValues"` BoolAttributeValues []bool `json:"boolAttributeValues"` + + RelatedValues *FilterAttributeValueResponse `json:"relatedValues"` } type QueryRangeParamsV3 struct {