diff --git a/pkg/query-service/app/logparsingpipeline/pipelineBuilder_test.go b/pkg/query-service/app/logparsingpipeline/pipelineBuilder_test.go index 47c340b9e3..d90f74a61e 100644 --- a/pkg/query-service/app/logparsingpipeline/pipelineBuilder_test.go +++ b/pkg/query-service/app/logparsingpipeline/pipelineBuilder_test.go @@ -717,6 +717,86 @@ func TestMembershipOpInProcessorFieldExpressions(t *testing.T) { require.Equal("pid0", result[0].Attributes_string["order.pids.pid0"]) } +func TestContainsFilterIsCaseInsensitive(t *testing.T) { + // The contains and ncontains query builder filters are case insensitive when querying logs. + // Pipeline filter should also behave in the same way. + require := require.New(t) + + testLogs := []model.SignozLog{ + makeTestSignozLog("test Ecom Log", map[string]interface{}{}), + } + + testPipelines := []Pipeline{{ + OrderId: 1, + Name: "pipeline1", + Alias: "pipeline1", + Enabled: true, + Filter: &v3.FilterSet{ + Operator: "AND", + Items: []v3.FilterItem{{ + Key: v3.AttributeKey{ + Key: "body", + DataType: v3.AttributeKeyDataTypeString, + Type: v3.AttributeKeyTypeUnspecified, + IsColumn: true, + }, + Operator: "contains", + Value: "log", + }}, + }, + Config: []PipelineOperator{ + { + ID: "add", + Type: "add", + Enabled: true, + Name: "add", + Field: "attributes.test1", + Value: "value1", + }, + }, + }, { + OrderId: 2, + Name: "pipeline2", + Alias: "pipeline2", + Enabled: true, + Filter: &v3.FilterSet{ + Operator: "AND", + Items: []v3.FilterItem{{ + Key: v3.AttributeKey{ + Key: "body", + DataType: v3.AttributeKeyDataTypeString, + Type: v3.AttributeKeyTypeUnspecified, + IsColumn: true, + }, + Operator: "ncontains", + Value: "ecom", + }}, + }, + Config: []PipelineOperator{ + { + ID: "add", + Type: "add", + Enabled: true, + Name: "add", + Field: "attributes.test2", + Value: "value2", + }, + }, + }} + + result, collectorWarnAndErrorLogs, err := SimulatePipelinesProcessing( + context.Background(), testPipelines, testLogs, + ) + require.Nil(err) + require.Equal(0, len(collectorWarnAndErrorLogs), strings.Join(collectorWarnAndErrorLogs, "\n")) + require.Equal(1, len(result)) + + require.Equal(result[0].Attributes_string["test1"], "value1") + + _, test2Exists := result[0].Attributes_string["test2"] + require.False(test2Exists) +} + func TestTemporaryWorkaroundForSupportingAttribsContainingDots(t *testing.T) { // TODO(Raj): Remove this after dots are supported diff --git a/pkg/query-service/queryBuilderToExpr/queryBuilderToExpr.go b/pkg/query-service/queryBuilderToExpr/queryBuilderToExpr.go index 8957d9f183..0139792dfa 100644 --- a/pkg/query-service/queryBuilderToExpr/queryBuilderToExpr.go +++ b/pkg/query-service/queryBuilderToExpr/queryBuilderToExpr.go @@ -73,9 +73,18 @@ func Parse(filters *v3.FilterSet) (string, error) { case v3.FilterOperatorExists, v3.FilterOperatorNotExists: filter = fmt.Sprintf("%s %s %s", exprFormattedValue(v.Key.Key), logOperatorsToExpr[v.Operator], getTypeName(v.Key.Type)) + default: filter = fmt.Sprintf("%s %s %s", name, logOperatorsToExpr[v.Operator], exprFormattedValue(v.Value)) + if v.Operator == v3.FilterOperatorContains || v.Operator == v3.FilterOperatorNotContains { + // `contains` and `ncontains` should be case insensitive to match how they work when querying logs. + filter = fmt.Sprintf( + "lower(%s) %s lower(%s)", + name, logOperatorsToExpr[v.Operator], exprFormattedValue(v.Value), + ) + } + // Avoid running operators on nil values if v.Operator != v3.FilterOperatorEqual && v.Operator != v3.FilterOperatorNotEqual { filter = fmt.Sprintf("%s != nil && %s", name, filter)