mirror of
https://github.com/SigNoz/signoz.git
synced 2026-02-03 08:33:26 +00:00
* feat: has JSON QB * fix: tests expected queries and values * fix: ignored .vscode in gitignore * fix: tests GroupBy * revert: gitignore change * fix: build json plans in metadata * fix: empty filteredArrays condition * fix: tests * fix: tests * fix: json qb test fix * fix: review based on tushar * fix: changes based on review from Srikanth * fix: remove unnecessary bool checking * fix: removed comment * chore: var renamed * fix: merge conflict * test: fix * fix: tests * fix: go test flakiness --------- Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
706 lines
23 KiB
Go
706 lines
23 KiB
Go
package telemetrylogs
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
|
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
|
"github.com/huandu/go-sqlbuilder"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestConditionFor(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
key telemetrytypes.TelemetryFieldKey
|
|
operator qbtypes.FilterOperator
|
|
value any
|
|
expectedSQL string
|
|
expectedArgs []any
|
|
expectedError error
|
|
}{
|
|
{
|
|
name: "Equal operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: "error message",
|
|
expectedSQL: "body = ?",
|
|
expectedArgs: []any{"error message"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Greater Than operator - number attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "request.duration",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeNumber,
|
|
},
|
|
operator: qbtypes.FilterOperatorGreaterThan,
|
|
value: float64(100),
|
|
expectedSQL: "(toFloat64(attributes_number['request.duration']) > ? AND mapContains(attributes_number, 'request.duration') = ?)",
|
|
expectedArgs: []any{float64(100), true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Less Than operator - number attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "request.size",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeNumber,
|
|
},
|
|
operator: qbtypes.FilterOperatorLessThan,
|
|
value: float64(1024),
|
|
expectedSQL: "(toFloat64(attributes_number['request.size']) < ? AND mapContains(attributes_number, 'request.size') = ?)",
|
|
expectedArgs: []any{float64(1024), true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Like operator - body",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorLike,
|
|
value: "%error%",
|
|
expectedSQL: "LOWER(body) LIKE LOWER(?)",
|
|
expectedArgs: []any{"%error%"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Like operator - body",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotLike,
|
|
value: "%error%",
|
|
expectedSQL: "LOWER(body) NOT LIKE LOWER(?)",
|
|
expectedArgs: []any{"%error%"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "ILike operator - string attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorILike,
|
|
value: "%admin%",
|
|
expectedSQL: "(LOWER(attributes_string['user.id']) LIKE LOWER(?) AND mapContains(attributes_string, 'user.id') = ?)",
|
|
expectedArgs: []any{"%admin%", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not ILike operator - string attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotILike,
|
|
value: "%admin%",
|
|
expectedSQL: "WHERE LOWER(attributes_string['user.id']) NOT LIKE LOWER(?)",
|
|
expectedArgs: []any{"%admin%"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Contains operator - string attribute number value",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorContains,
|
|
value: 521509198310,
|
|
expectedSQL: "LOWER(attributes_string['user.id']) LIKE LOWER(?)",
|
|
expectedArgs: []any{"%521509198310%", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Contains operator - body",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
},
|
|
operator: qbtypes.FilterOperatorContains,
|
|
value: 521509198310,
|
|
expectedSQL: "LOWER(body) LIKE LOWER(?)",
|
|
expectedArgs: []any{"%521509198310%"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Contains operator - string attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorContains,
|
|
value: "admin",
|
|
expectedSQL: "(LOWER(attributes_string['user.id']) LIKE LOWER(?) AND mapContains(attributes_string, 'user.id') = ?)",
|
|
expectedArgs: []any{"%admin%", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "In operator - severity_text",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "severity_text",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorIn,
|
|
value: []any{"error", "fatal", "critical"},
|
|
expectedSQL: "(severity_text = ? OR severity_text = ? OR severity_text = ?)",
|
|
expectedArgs: []any{"error", "fatal", "critical"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "In operator - invalid value",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "severity_text",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorIn,
|
|
value: "error",
|
|
expectedSQL: "",
|
|
expectedError: qbtypes.ErrInValues,
|
|
},
|
|
{
|
|
name: "Not In operator - severity_text",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "severity_text",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotIn,
|
|
value: []any{"debug", "info", "trace"},
|
|
expectedSQL: "(severity_text <> ? AND severity_text <> ? AND severity_text <> ?)",
|
|
expectedArgs: []any{"debug", "info", "trace"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Exists operator - string field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorExists,
|
|
value: nil,
|
|
expectedSQL: "WHERE body <> ?",
|
|
expectedArgs: []any{""},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Exists operator - string field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotExists,
|
|
value: nil,
|
|
expectedSQL: "WHERE body = ?",
|
|
expectedArgs: []any{""},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Exists operator - map field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorExists,
|
|
value: nil,
|
|
expectedSQL: "mapContains(attributes_string, 'user.id') = ?",
|
|
expectedArgs: []any{true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Exists operator - map field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotExists,
|
|
value: nil,
|
|
expectedSQL: "mapContains(attributes_string, 'user.id') <> ?",
|
|
expectedArgs: []any{true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Exists operator - json field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "service.name",
|
|
FieldContext: telemetrytypes.FieldContextResource,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorExists,
|
|
value: nil,
|
|
expectedSQL: "WHERE multiIf(resource.`service.name` IS NOT NULL, resource.`service.name`::String, mapContains(resources_string, 'service.name'), resources_string['service.name'], NULL) IS NOT NULL",
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Exists operator - json field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "service.name",
|
|
FieldContext: telemetrytypes.FieldContextResource,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotExists,
|
|
value: nil,
|
|
expectedSQL: "WHERE multiIf(resource.`service.name` IS NOT NULL, resource.`service.name`::String, mapContains(resources_string, 'service.name'), resources_string['service.name'], NULL) IS NULL",
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Regexp operator - body field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorRegexp,
|
|
value: "error.*failed",
|
|
expectedSQL: "match(LOWER(body), LOWER(?))",
|
|
expectedArgs: []any{"error.*failed"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Regexp operator - body field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotRegexp,
|
|
value: "debug|trace",
|
|
expectedSQL: "NOT match(LOWER(body), LOWER(?))",
|
|
expectedArgs: []any{"debug|trace"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Regexp operator - string attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.url",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorRegexp,
|
|
value: "^https://.*\\.example\\.com.*$",
|
|
expectedSQL: "(match(attributes_string['http.url'], ?) AND mapContains(attributes_string, 'http.url') = ?)",
|
|
expectedArgs: []any{"^https://.*\\.example\\.com.*$", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Regexp operator - string attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.url",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotRegexp,
|
|
value: "^http://localhost.*",
|
|
expectedSQL: "WHERE NOT match(attributes_string['http.url'], ?)",
|
|
expectedArgs: []any{"^http://localhost.*"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Regexp operator - resource attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "service.name",
|
|
FieldContext: telemetrytypes.FieldContextResource,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
Materialized: true,
|
|
},
|
|
operator: qbtypes.FilterOperatorRegexp,
|
|
value: "frontend-.*",
|
|
expectedSQL: "(match(multiIf(resource.`service.name` IS NOT NULL, resource.`service.name`::String, `resource_string_service$$name_exists`==true, `resource_string_service$$name`, NULL), ?) AND multiIf(resource.`service.name` IS NOT NULL, resource.`service.name`::String, `resource_string_service$$name_exists`==true, `resource_string_service$$name`, NULL) IS NOT NULL)",
|
|
expectedArgs: []any{"frontend-.*"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Regexp operator - resource attribute",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "service.name",
|
|
FieldContext: telemetrytypes.FieldContextResource,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
Materialized: true,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotRegexp,
|
|
value: "test-.*",
|
|
expectedSQL: "WHERE NOT match(multiIf(resource.`service.name` IS NOT NULL, resource.`service.name`::String, `resource_string_service$$name_exists`==true, `resource_string_service$$name`, NULL), ?)",
|
|
expectedArgs: []any{"test-.*"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Regexp operator - severity_text",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "severity_text",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorRegexp,
|
|
value: "ERROR|FATAL|CRITICAL",
|
|
expectedSQL: "match(severity_text, ?)",
|
|
expectedArgs: []any{"ERROR|FATAL|CRITICAL"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Regexp operator - severity_text",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "severity_text",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotRegexp,
|
|
value: "DEBUG|TRACE",
|
|
expectedSQL: "NOT match(severity_text, ?)",
|
|
expectedArgs: []any{"DEBUG|TRACE"},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Non-existent column",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "nonexistent_field",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: "value",
|
|
expectedSQL: "",
|
|
expectedError: qbtypes.ErrColumnNotFound,
|
|
},
|
|
}
|
|
|
|
fm := NewFieldMapper()
|
|
conditionBuilder := NewConditionBuilder(fm)
|
|
|
|
for _, tc := range testCases {
|
|
sb := sqlbuilder.NewSelectBuilder()
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cond, err := conditionBuilder.ConditionFor(ctx, &tc.key, tc.operator, tc.value, sb, 0, 0)
|
|
sb.Where(cond)
|
|
|
|
if tc.expectedError != nil {
|
|
assert.Equal(t, tc.expectedError, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
sql, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
|
|
assert.Contains(t, sql, tc.expectedSQL)
|
|
assert.Equal(t, tc.expectedArgs, args)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConditionForMultipleKeys(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
keys []telemetrytypes.TelemetryFieldKey
|
|
operator qbtypes.FilterOperator
|
|
value any
|
|
expectedSQL string
|
|
expectedArgs []any
|
|
expectedError error
|
|
}{
|
|
{
|
|
name: "Equal operator - string",
|
|
keys: []telemetrytypes.TelemetryFieldKey{
|
|
{
|
|
Name: "body",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
{
|
|
Name: "severity_text",
|
|
FieldContext: telemetrytypes.FieldContextLog,
|
|
},
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: "error message",
|
|
expectedSQL: "body = ? AND severity_text = ?",
|
|
expectedArgs: []any{"error message", "error message"},
|
|
expectedError: nil,
|
|
},
|
|
}
|
|
|
|
fm := NewFieldMapper()
|
|
conditionBuilder := NewConditionBuilder(fm)
|
|
|
|
for _, tc := range testCases {
|
|
sb := sqlbuilder.NewSelectBuilder()
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
var err error
|
|
for _, key := range tc.keys {
|
|
cond, err := conditionBuilder.ConditionFor(ctx, &key, tc.operator, tc.value, sb, 0, 0)
|
|
sb.Where(cond)
|
|
if err != nil {
|
|
t.Fatalf("Error getting condition for key %s: %v", key.Name, err)
|
|
}
|
|
}
|
|
|
|
if tc.expectedError != nil {
|
|
assert.Equal(t, tc.expectedError, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
sql, _ := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
|
|
assert.Contains(t, sql, tc.expectedSQL)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConditionForJSONBodySearch(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
key telemetrytypes.TelemetryFieldKey
|
|
operator qbtypes.FilterOperator
|
|
value any
|
|
expectedSQL string
|
|
expectedError error
|
|
}{
|
|
{
|
|
name: "Equal operator - int64",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: 200,
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') = ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Equal operator - float64",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "duration_ms",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: 405.5,
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."duration_ms"'), 'Float64') = ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Equal operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.method",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: "GET",
|
|
expectedSQL: `JSON_VALUE(body, '$."http"."method"') = ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Equal operator - bool",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.success",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorEqual,
|
|
value: true,
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."success"'), 'Bool') = ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Exists operator",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorExists,
|
|
value: nil,
|
|
expectedSQL: `JSON_EXISTS(body, '$."http"."status_code"')`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Exists operator",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotExists,
|
|
value: nil,
|
|
expectedSQL: `NOT JSON_EXISTS(body, '$."http"."status_code"')`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Greater than operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorGreaterThan,
|
|
value: "200",
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') > ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Greater than operator - int64",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorGreaterThan,
|
|
value: 200,
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') > ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Less than operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorLessThan,
|
|
value: "300",
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') < ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Less than operator - int64",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorLessThan,
|
|
value: 300,
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') < ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Contains operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorContains,
|
|
value: "200",
|
|
expectedSQL: `LOWER(JSON_VALUE(body, '$."http"."status_code"')) LIKE LOWER(?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Contains operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotContains,
|
|
value: "200",
|
|
expectedSQL: `LOWER(JSON_VALUE(body, '$."http"."status_code"')) NOT LIKE LOWER(?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Between operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorBetween,
|
|
value: []any{"200", "300"},
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') BETWEEN ? AND ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Between operator - int64",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorBetween,
|
|
value: []any{400, 500},
|
|
expectedSQL: `JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') BETWEEN ? AND ?`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "In operator - string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorIn,
|
|
value: []any{"200", "300"},
|
|
expectedSQL: `(JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') = ? OR JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') = ?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "In operator - int64",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.status_code",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorIn,
|
|
value: []any{401, 404, 500},
|
|
expectedSQL: `(JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') = ? OR JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') = ? OR JSONExtract(JSON_VALUE(body, '$."http"."status_code"'), 'Int64') = ?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Regexp operator - json body string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.method",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorRegexp,
|
|
value: "GET|POST|PUT",
|
|
expectedSQL: `match(JSON_VALUE(body, '$."http"."method"'), ?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Regexp operator - json body string",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "http.method",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotRegexp,
|
|
value: "DELETE|PATCH",
|
|
expectedSQL: `NOT match(JSON_VALUE(body, '$."http"."method"'), ?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Regexp operator - json body with dots in path",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.email",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorRegexp,
|
|
value: "^.*@example\\.com$",
|
|
expectedSQL: `match(JSON_VALUE(body, '$."user"."email"'), ?)`,
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not Regexp operator - json body nested path",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "response.headers.content-type",
|
|
FieldContext: telemetrytypes.FieldContextBody,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotRegexp,
|
|
value: "^text/.*",
|
|
expectedSQL: `NOT match(JSON_VALUE(body, '$."response"."headers"."content-type"'), ?)`,
|
|
expectedError: nil,
|
|
},
|
|
}
|
|
|
|
fm := NewFieldMapper()
|
|
conditionBuilder := NewConditionBuilder(fm)
|
|
|
|
for _, tc := range testCases {
|
|
sb := sqlbuilder.NewSelectBuilder()
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cond, err := conditionBuilder.ConditionFor(ctx, &tc.key, tc.operator, tc.value, sb, 0, 0)
|
|
sb.Where(cond)
|
|
|
|
if tc.expectedError != nil {
|
|
assert.Equal(t, tc.expectedError, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
sql, _ := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
|
|
assert.Contains(t, sql, tc.expectedSQL)
|
|
}
|
|
})
|
|
}
|
|
}
|