Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: enrich attributes regardless if it is materialized #6000

Merged
merged 8 commits into from
Oct 9, 2024
30 changes: 12 additions & 18 deletions pkg/query-service/app/logs/v3/enrich_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"go.signoz.io/signoz/pkg/query-service/constants"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/utils"
)

func EnrichmentRequired(params *v3.QueryRangeParamsV3) bool {
Expand Down Expand Up @@ -61,26 +62,23 @@ func EnrichmentRequired(params *v3.QueryRangeParamsV3) bool {
return false
}

// if the field is timestamp/id/value we don't need to enrich
// if the field is static we don't need to enrich
// for all others we need to enrich
// an attribute/resource can be materialized/dematerialized
// but the query should work regardless and shouldn't fail
func isEnriched(field v3.AttributeKey) bool {
// if it is timestamp/id dont check
if field.Key == "timestamp" || field.Key == "id" || field.Key == constants.SigNozOrderByValue {
return true
}

if field.IsColumn {
// don't need to enrich the static fields as they will be always used a column
if _, ok := constants.StaticFieldsLogsV3[field.Key]; ok && field.IsColumn {
return true
}

if field.Type == v3.AttributeKeyTypeUnspecified || field.DataType == v3.AttributeKeyDataTypeUnspecified {
return false
}

// try to enrich all attributes which doesn't have isColumn = true
if !field.IsColumn {
return false
}

return true
return false
}

func Enrich(params *v3.QueryRangeParamsV3, fields map[string]v3.AttributeKey) {
Expand Down Expand Up @@ -144,13 +142,9 @@ func enrichFieldWithMetadata(field v3.AttributeKey, fields map[string]v3.Attribu
}

// check if the field is present in the fields map
if existingField, ok := fields[field.Key]; ok {
// don't update if type is not the same
if (field.Type == "" && field.DataType == "") ||
(field.Type == existingField.Type && field.DataType == existingField.DataType) ||
(field.Type == "" && field.DataType == existingField.DataType) ||
(field.DataType == "" && field.Type == existingField.Type) {
return existingField
for _, key := range utils.GenerateLogEnrichmentKeys(field) {
if val, ok := fields[key]; ok {
return val
nityanandagohain marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
90 changes: 78 additions & 12 deletions pkg/query-service/app/logs/v3/enrich_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var testEnrichmentRequiredData = []struct {
EnrichmentRequired: true,
},
{
Name: "filter enrichment not required",
Name: "filter enrichment required",
Params: v3.QueryRangeParamsV3{
CompositeQuery: &v3.CompositeQuery{
BuilderQueries: map[string]*v3.BuilderQuery{
Expand Down Expand Up @@ -87,7 +87,7 @@ var testEnrichmentRequiredData = []struct {
EnrichmentRequired: true,
},
{
Name: "filter enrichment not required required json",
Name: "filter enrichment required required json",
Params: v3.QueryRangeParamsV3{
CompositeQuery: &v3.CompositeQuery{
BuilderQueries: map[string]*v3.BuilderQuery{
Expand All @@ -105,7 +105,7 @@ var testEnrichmentRequiredData = []struct {
EnrichmentRequired: true,
},
{
Name: "groupBy enrichment not required",
Name: "groupBy enrichment required",
Params: v3.QueryRangeParamsV3{
CompositeQuery: &v3.CompositeQuery{
BuilderQueries: map[string]*v3.BuilderQuery{
Expand Down Expand Up @@ -194,8 +194,9 @@ var testEnrichmentRequiredData = []struct {
QueryName: "test",
Expression: "test",
DataSource: v3.DataSourceLogs,
GroupBy: []v3.AttributeKey{{Key: "trace_id", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
OrderBy: []v3.OrderBy{{ColumnName: "#SIGNOZ_VALUE", Order: "ASC"}},
// here we have to fallback to trace_id attribute instead of column
GroupBy: []v3.AttributeKey{{Key: "trace_id", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
OrderBy: []v3.OrderBy{{ColumnName: "#SIGNOZ_VALUE", Order: "ASC"}},
},
},
},
Expand Down Expand Up @@ -241,17 +242,17 @@ var testEnrichParamsData = []struct {
},
},
Fields: map[string]v3.AttributeKey{
"test": {
"test##tag##int64": {
Key: "test",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeInt64,
},
"user_name": {
"user_name##tag##string": {
Key: "user_name",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
},
"response_time": {
"response_time##tag##int64": {
Key: "response_time",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeInt64,
Expand Down Expand Up @@ -302,18 +303,18 @@ var testEnrichParamsData = []struct {
},
},
Fields: map[string]v3.AttributeKey{
"method.name": {
"method.name##tag##string": {
Key: "method.name",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
IsColumn: true,
},
"service.name": {
"service.name##tag##string": {
Key: "service.name",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
},
"host.name": {
"host.name##tag##string": {
Key: "host.name",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
Expand Down Expand Up @@ -365,7 +366,7 @@ var testEnrichParamsData = []struct {
},
},
Fields: map[string]v3.AttributeKey{
"test": {
"test##tag##string": {
Key: "test",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
Expand Down Expand Up @@ -393,6 +394,71 @@ var testEnrichParamsData = []struct {
},
},
},
{
Name: "Enrich if an attribute/resource attribute is materialized/dematerialized",
Params: v3.QueryRangeParamsV3{
CompositeQuery: &v3.CompositeQuery{
BuilderQueries: map[string]*v3.BuilderQuery{
"test": {
QueryName: "test",
Expression: "test",
DataSource: v3.DataSourceLogs,
AggregateAttribute: v3.AttributeKey{
Key: "mat_resource",
Type: v3.AttributeKeyTypeResource,
DataType: v3.AttributeKeyDataTypeInt64,
IsColumn: true,
},
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
{Key: v3.AttributeKey{Key: "mat_attr", Type: v3.AttributeKeyTypeTag, IsColumn: true}, Value: "test", Operator: "="},
{Key: v3.AttributeKey{Key: "normal_attr", DataType: v3.AttributeKeyDataTypeString, IsColumn: false}, Value: "test1", Operator: "="},
}},
},
},
},
},
Fields: map[string]v3.AttributeKey{
"mat_resource##resource##int64": {
Key: "mat_resource",
Type: v3.AttributeKeyTypeResource,
DataType: v3.AttributeKeyDataTypeInt64,
IsColumn: false,
},
"mat_attr##tag##string": {
Key: "mat_attr",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
IsColumn: false,
},
"normal_attr##tag##string": {
Key: "normal_attr",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
IsColumn: true,
},
},
Result: v3.QueryRangeParamsV3{
CompositeQuery: &v3.CompositeQuery{
BuilderQueries: map[string]*v3.BuilderQuery{
"test": {
QueryName: "test",
Expression: "test",
DataSource: v3.DataSourceLogs,
AggregateAttribute: v3.AttributeKey{
Key: "mat_resource",
Type: v3.AttributeKeyTypeResource,
DataType: v3.AttributeKeyDataTypeInt64,
IsColumn: false,
},
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
{Key: v3.AttributeKey{Key: "mat_attr", Type: v3.AttributeKeyTypeTag, DataType: v3.AttributeKeyDataTypeString, IsColumn: false}, Value: "test", Operator: "="},
{Key: v3.AttributeKey{Key: "normal_attr", Type: v3.AttributeKeyTypeTag, DataType: v3.AttributeKeyDataTypeString, IsColumn: true}, Value: "test1", Operator: "="},
}},
},
},
},
},
},
}

func TestEnrichParams(t *testing.T) {
Expand Down
23 changes: 21 additions & 2 deletions pkg/query-service/contextlinks/links.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

tracesV3 "go.signoz.io/signoz/pkg/query-service/app/traces/v3"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/utils"
)

func PrepareLinksToTraces(start, end time.Time, filterItems []v3.FilterItem) string {
Expand Down Expand Up @@ -178,8 +179,26 @@ func PrepareFilters(labels map[string]string, whereClauseItems []v3.FilterItem,
for key, value := range labels {
if _, ok := added[key]; !ok {
// start by taking the attribute key from the keys map, if not present, create a new one
attributeKey, ok := keys[key]
if !ok {
var attributeKey v3.AttributeKey
var attrFound bool

// as of now this logic will only apply for logs
for _, tKey := range utils.GenerateLogEnrichmentKeys(v3.AttributeKey{Key: key}) {
if val, ok := keys[tKey]; ok {
attributeKey = val
attrFound = true
break
}
}

// check if the attribute key is directly present, as of now this will always be false for logs
// as for logs it will be satisfied in the condition above
if !attrFound {
attributeKey, attrFound = keys[key]
}

// if the attribute key is not present, create a new one
if !attrFound {
attributeKey = v3.AttributeKey{Key: key}
}

Expand Down
7 changes: 5 additions & 2 deletions pkg/query-service/model/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func GetLogFieldsV3(ctx context.Context, queryRangeParams *v3.QueryRangeParamsV3
if pass {
continue
}
data[selectedField.Name] = v3.AttributeKey{
name := selectedField.Name + "##" + fieldType.String() + "##" + strings.ToLower(selectedField.DataType)
data[name] = v3.AttributeKey{
nityanandagohain marked this conversation as resolved.
Show resolved Hide resolved
Key: selectedField.Name,
Type: fieldType,
DataType: v3.AttributeKeyDataType(strings.ToLower(selectedField.DataType)),
Expand All @@ -61,12 +62,14 @@ func GetLogFieldsV3(ctx context.Context, queryRangeParams *v3.QueryRangeParamsV3
if pass {
continue
}
data[interestingField.Name] = v3.AttributeKey{
name := interestingField.Name + "##" + fieldType.String() + "##" + strings.ToLower(interestingField.DataType)
data[name] = v3.AttributeKey{
Key: interestingField.Name,
Type: fieldType,
DataType: v3.AttributeKeyDataType(strings.ToLower(interestingField.DataType)),
IsColumn: false,
}

}
break
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/query-service/model/v3/v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ func (q AttributeKeyDataType) Validate() error {
}
}

func (q AttributeKeyDataType) String() string {
return string(q)
}

// FilterAttributeValueRequest is a request to fetch possible attribute values
// for a selected aggregate operator, aggregate attribute, filter attribute key
// and search text.
Expand Down Expand Up @@ -317,6 +321,10 @@ const (
AttributeKeyTypeResource AttributeKeyType = "resource"
)

func (t AttributeKeyType) String() string {
return string(t)
}

type AttributeKey struct {
Key string `json:"key"`
DataType AttributeKeyDataType `json:"dataType"`
Expand Down
33 changes: 33 additions & 0 deletions pkg/query-service/utils/logs.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package utils

import v3 "go.signoz.io/signoz/pkg/query-service/model/v3"

const HOUR_NANO = int64(3600000000000)

type LogsListTsRange struct {
Expand Down Expand Up @@ -36,3 +38,34 @@ func GetLogsListTsRanges(start, end int64) []LogsListTsRange {
}
return result
}

// This tries to see all possible fields that it can fall back to if some meta is missing
// check Test_GenerateLogEnrichmentKeys for example
func GenerateLogEnrichmentKeys(field v3.AttributeKey) []string {
names := []string{}
if field.Type != v3.AttributeKeyTypeUnspecified && field.DataType != v3.AttributeKeyDataTypeUnspecified {
names = append(names, field.Key+"##"+field.Type.String()+"##"+field.DataType.String())
return names
}

types := []v3.AttributeKeyType{}
dTypes := []v3.AttributeKeyDataType{}
if field.Type != v3.AttributeKeyTypeUnspecified {
types = append(types, field.Type)
} else {
types = append(types, v3.AttributeKeyTypeTag, v3.AttributeKeyTypeResource)
}
if field.DataType != v3.AttributeKeyDataTypeUnspecified {
dTypes = append(dTypes, field.DataType)
} else {
dTypes = append(dTypes, v3.AttributeKeyDataTypeFloat64, v3.AttributeKeyDataTypeInt64, v3.AttributeKeyDataTypeString, v3.AttributeKeyDataTypeBool)
}

for _, t := range types {
for _, d := range dTypes {
names = append(names, field.Key+"##"+t.String()+"##"+d.String())
}
}

return names
}
Loading
Loading