mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-28 05:41:58 +08:00
255 lines
8.5 KiB
Go
255 lines
8.5 KiB
Go
package telemetrytraces
|
|
|
|
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: "Not Equal operator - timestamp",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotEqual,
|
|
value: uint64(1617979338000000000),
|
|
expectedSQL: "timestamp <> ?",
|
|
expectedArgs: []any{uint64(1617979338000000000)},
|
|
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: "(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: "(attributes_number['request.size'] < ? AND mapContains(attributes_number, 'request.size') = ?)",
|
|
expectedArgs: []any{float64(1024), true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Greater Than Or Equal operator - timestamp",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorGreaterThanOrEq,
|
|
value: uint64(1617979338000000000),
|
|
expectedSQL: "timestamp >= ?",
|
|
expectedArgs: []any{uint64(1617979338000000000)},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Less Than Or Equal operator - timestamp",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorLessThanOrEq,
|
|
value: uint64(1617979338000000000),
|
|
expectedSQL: "timestamp <= ?",
|
|
expectedArgs: []any{uint64(1617979338000000000)},
|
|
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%", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Between operator - timestamp",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorBetween,
|
|
value: []any{uint64(1617979338000000000), uint64(1617979348000000000)},
|
|
expectedSQL: "timestamp BETWEEN ? AND ?",
|
|
expectedArgs: []any{uint64(1617979338000000000), uint64(1617979348000000000)},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Between operator - invalid value",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorBetween,
|
|
value: "invalid",
|
|
expectedSQL: "",
|
|
expectedError: qbtypes.ErrBetweenValues,
|
|
},
|
|
{
|
|
name: "Between operator - insufficient values",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorBetween,
|
|
value: []any{uint64(1617979338000000000)},
|
|
expectedSQL: "",
|
|
expectedError: qbtypes.ErrBetweenValues,
|
|
},
|
|
{
|
|
name: "Not Between operator - timestamp",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "timestamp",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotBetween,
|
|
value: []any{uint64(1617979338000000000), uint64(1617979348000000000)},
|
|
expectedSQL: "timestamp NOT BETWEEN ? AND ?",
|
|
expectedArgs: []any{uint64(1617979338000000000), uint64(1617979348000000000)},
|
|
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') = ?",
|
|
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') <> ?",
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Contains operator - map field",
|
|
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 - map field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorIn,
|
|
value: []any{"admin", "user"},
|
|
expectedSQL: "((attributes_string['user.id'] = ? OR attributes_string['user.id'] = ?) AND mapContains(attributes_string, 'user.id') = ?)",
|
|
expectedArgs: []any{"admin", "user", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Not In operator - map field",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "user.id",
|
|
FieldContext: telemetrytypes.FieldContextAttribute,
|
|
FieldDataType: telemetrytypes.FieldDataTypeString,
|
|
},
|
|
operator: qbtypes.FilterOperatorNotIn,
|
|
value: []any{"admin", "user"},
|
|
expectedSQL: "(attributes_string['user.id'] <> ? AND attributes_string['user.id'] <> ?)",
|
|
expectedArgs: []any{"admin", "user", true},
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
name: "Non-existent column",
|
|
key: telemetrytypes.TelemetryFieldKey{
|
|
Name: "nonexistent_field",
|
|
FieldContext: telemetrytypes.FieldContextSpan,
|
|
},
|
|
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)
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
}
|