mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-13 03:11:48 +08:00

* feat: support for case insensitive for contains and like queries * fix: make index filter lowercase for like and not like
1108 lines
38 KiB
Go
1108 lines
38 KiB
Go
package v4
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"go.signoz.io/signoz/pkg/query-service/constants"
|
|
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
|
)
|
|
|
|
func Test_getClickhouseKey(t *testing.T) {
|
|
type args struct {
|
|
key v3.AttributeKey
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "attribute",
|
|
args: args{
|
|
key: v3.AttributeKey{Key: "user_name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag},
|
|
},
|
|
want: "attributes_string['user_name']",
|
|
},
|
|
{
|
|
name: "resource",
|
|
args: args{
|
|
key: v3.AttributeKey{Key: "servicename", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource},
|
|
},
|
|
want: "resources_string['servicename']",
|
|
},
|
|
{
|
|
name: "selected field",
|
|
args: args{
|
|
key: v3.AttributeKey{Key: "bytes", DataType: v3.AttributeKeyDataTypeFloat64, Type: v3.AttributeKeyTypeTag, IsColumn: true},
|
|
},
|
|
want: "`attribute_number_bytes`",
|
|
},
|
|
{
|
|
name: "selected field resource",
|
|
args: args{
|
|
key: v3.AttributeKey{Key: "servicename", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource, IsColumn: true},
|
|
},
|
|
want: "`resource_string_servicename`",
|
|
},
|
|
{
|
|
name: "top level key",
|
|
args: args{
|
|
key: v3.AttributeKey{Key: "trace_id", DataType: v3.AttributeKeyDataTypeString},
|
|
},
|
|
want: "trace_id",
|
|
},
|
|
{
|
|
name: "name with -",
|
|
args: args{
|
|
key: v3.AttributeKey{Key: "service-name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag, IsColumn: true},
|
|
},
|
|
want: "`attribute_string_service-name`",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := getClickhouseKey(tt.args.key); got != tt.want {
|
|
t.Errorf("getClickhouseKey() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_getSelectLabels(t *testing.T) {
|
|
type args struct {
|
|
aggregatorOperator v3.AggregateOperator
|
|
groupBy []v3.AttributeKey
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "count",
|
|
args: args{
|
|
aggregatorOperator: v3.AggregateOperatorCount,
|
|
groupBy: []v3.AttributeKey{{Key: "user_name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
},
|
|
want: " attributes_string['user_name'] as `user_name`,",
|
|
},
|
|
{
|
|
name: "multiple group by",
|
|
args: args{
|
|
aggregatorOperator: v3.AggregateOperatorCount,
|
|
groupBy: []v3.AttributeKey{
|
|
{Key: "user_name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag},
|
|
{Key: "service_name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource, IsColumn: true},
|
|
},
|
|
},
|
|
want: " attributes_string['user_name'] as `user_name`, `resource_string_service_name` as `service_name`,",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := getSelectLabels(tt.args.aggregatorOperator, tt.args.groupBy); got != tt.want {
|
|
t.Errorf("getSelectLabels() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_getExistsNexistsFilter(t *testing.T) {
|
|
type args struct {
|
|
op v3.FilterOperator
|
|
item v3.FilterItem
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "exists",
|
|
args: args{
|
|
op: v3.FilterOperatorExists,
|
|
item: v3.FilterItem{Key: v3.AttributeKey{Key: "user_name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
},
|
|
want: "mapContains(attributes_string, 'user_name')",
|
|
},
|
|
{
|
|
name: "not exists",
|
|
args: args{
|
|
op: v3.FilterOperatorNotExists,
|
|
item: v3.FilterItem{Key: v3.AttributeKey{Key: "user_name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
},
|
|
want: "not mapContains(attributes_string, 'user_name')",
|
|
},
|
|
{
|
|
name: "exists mat column",
|
|
args: args{
|
|
op: v3.FilterOperatorExists,
|
|
item: v3.FilterItem{Key: v3.AttributeKey{Key: "bytes", DataType: v3.AttributeKeyDataTypeFloat64, Type: v3.AttributeKeyTypeTag, IsColumn: true}},
|
|
},
|
|
want: "`attribute_number_bytes_exists`=true",
|
|
},
|
|
{
|
|
name: "exists top level column",
|
|
args: args{
|
|
op: v3.FilterOperatorExists,
|
|
item: v3.FilterItem{Key: v3.AttributeKey{Key: "trace_id", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeUnspecified}},
|
|
},
|
|
want: "trace_id != ''",
|
|
},
|
|
{
|
|
name: "exists top level column- number",
|
|
args: args{
|
|
op: v3.FilterOperatorNotExists,
|
|
item: v3.FilterItem{Key: v3.AttributeKey{Key: "severity_number", DataType: v3.AttributeKeyDataTypeArrayFloat64, Type: v3.AttributeKeyTypeUnspecified}},
|
|
},
|
|
want: "severity_number = 0",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := getExistsNexistsFilter(tt.args.op, tt.args.item); got != tt.want {
|
|
t.Errorf("getExistsNexistsFilter() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_buildAttributeFilter(t *testing.T) {
|
|
type args struct {
|
|
item v3.FilterItem
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "build attribute filter",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
},
|
|
want: "resources_string['service.name'] = 'test'",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "test for value search across all attributes",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "__attrs",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
},
|
|
Operator: v3.FilterOperatorContains,
|
|
Value: "test",
|
|
},
|
|
},
|
|
want: "has(mapValues(attributes_string), 'test')",
|
|
},
|
|
{
|
|
name: "build attribute filter exists",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
Operator: v3.FilterOperatorExists,
|
|
},
|
|
},
|
|
want: "mapContains(resources_string, 'service.name')",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "build attribute filter regex",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
Operator: v3.FilterOperatorRegex,
|
|
Value: "^test",
|
|
},
|
|
},
|
|
want: "match(resources_string['service.name'], '^test')",
|
|
},
|
|
{
|
|
name: "build attribute filter contains",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
Operator: v3.FilterOperatorContains,
|
|
Value: "test",
|
|
},
|
|
},
|
|
want: "resources_string['service.name'] ILIKE '%test%'",
|
|
},
|
|
{
|
|
name: "build attribute filter contains- body",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "body",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
IsColumn: true,
|
|
},
|
|
Operator: v3.FilterOperatorContains,
|
|
Value: "test",
|
|
},
|
|
},
|
|
want: "lower(body) LIKE lower('%test%')",
|
|
},
|
|
{
|
|
name: "build attribute filter like",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
Operator: v3.FilterOperatorLike,
|
|
Value: "test%",
|
|
},
|
|
},
|
|
want: "resources_string['service.name'] ILIKE 'test%'",
|
|
},
|
|
{
|
|
name: "build attribute filter like-body",
|
|
args: args{
|
|
item: v3.FilterItem{
|
|
Key: v3.AttributeKey{
|
|
Key: "body",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
IsColumn: true,
|
|
},
|
|
Operator: v3.FilterOperatorLike,
|
|
Value: "test",
|
|
},
|
|
},
|
|
want: "lower(body) LIKE lower('test')",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := buildAttributeFilter(tt.args.item)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("buildAttributeFilter() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("buildAttributeFilter() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_buildLogsTimeSeriesFilterQuery(t *testing.T) {
|
|
type args struct {
|
|
fs *v3.FilterSet
|
|
groupBy []v3.AttributeKey
|
|
aggregateAttribute v3.AttributeKey
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "build logs time series filter query",
|
|
args: args{
|
|
fs: &v3.FilterSet{
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "method",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "GET",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: "attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') " +
|
|
"AND attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method')",
|
|
},
|
|
{
|
|
name: "build logs time series filter query with group by and aggregate attribute",
|
|
args: args{
|
|
fs: &v3.FilterSet{
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
},
|
|
},
|
|
groupBy: []v3.AttributeKey{
|
|
{
|
|
Key: "user_name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
},
|
|
aggregateAttribute: v3.AttributeKey{
|
|
Key: "test",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
},
|
|
want: "attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') " +
|
|
"AND mapContains(attributes_string, 'user_name') AND mapContains(attributes_string, 'test')",
|
|
},
|
|
{
|
|
name: "build logs time series filter query with multiple group by and aggregate attribute",
|
|
args: args{
|
|
fs: &v3.FilterSet{
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
},
|
|
},
|
|
groupBy: []v3.AttributeKey{
|
|
{
|
|
Key: "user_name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
{
|
|
Key: "host",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
{
|
|
Key: "method",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
IsColumn: true,
|
|
},
|
|
{
|
|
Key: "trace_id",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
IsColumn: true,
|
|
},
|
|
},
|
|
aggregateAttribute: v3.AttributeKey{
|
|
Key: "test",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
},
|
|
want: "attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') " +
|
|
"AND mapContains(attributes_string, 'user_name') AND `attribute_string_method_exists`=true AND mapContains(attributes_string, 'test')",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := buildLogsTimeSeriesFilterQuery(tt.args.fs, tt.args.groupBy, tt.args.aggregateAttribute)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("buildLogsTimeSeriesFilterQuery() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("buildLogsTimeSeriesFilterQuery() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_orderByAttributeKeyTags(t *testing.T) {
|
|
type args struct {
|
|
panelType v3.PanelType
|
|
items []v3.OrderBy
|
|
tags []v3.AttributeKey
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "Test 1",
|
|
args: args{
|
|
panelType: v3.PanelTypeGraph,
|
|
items: []v3.OrderBy{
|
|
{
|
|
ColumnName: "name",
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: constants.SigNozOrderByValue,
|
|
Order: "desc",
|
|
},
|
|
},
|
|
tags: []v3.AttributeKey{
|
|
{Key: "name"},
|
|
},
|
|
},
|
|
want: "`name` asc,value desc",
|
|
},
|
|
{
|
|
name: "Test Graph item not present in tag",
|
|
args: args{
|
|
panelType: v3.PanelTypeGraph,
|
|
items: []v3.OrderBy{
|
|
{
|
|
ColumnName: "name",
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: "bytes",
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: "method",
|
|
Order: "asc",
|
|
},
|
|
},
|
|
tags: []v3.AttributeKey{
|
|
{Key: "name"},
|
|
{Key: "bytes"},
|
|
},
|
|
},
|
|
want: "`name` asc,`bytes` asc",
|
|
},
|
|
{
|
|
name: "Test panel list",
|
|
args: args{
|
|
panelType: v3.PanelTypeList,
|
|
items: []v3.OrderBy{
|
|
{
|
|
ColumnName: "name",
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: constants.SigNozOrderByValue,
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: "bytes",
|
|
Order: "asc",
|
|
},
|
|
},
|
|
tags: []v3.AttributeKey{
|
|
{Key: "name"},
|
|
{Key: "bytes"},
|
|
},
|
|
},
|
|
want: "`name` asc,value asc,`bytes` asc",
|
|
},
|
|
{
|
|
name: "test 4",
|
|
args: args{
|
|
panelType: v3.PanelTypeList,
|
|
items: []v3.OrderBy{
|
|
{
|
|
ColumnName: "name",
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: constants.SigNozOrderByValue,
|
|
Order: "asc",
|
|
},
|
|
{
|
|
ColumnName: "response_time",
|
|
Order: "desc",
|
|
Key: "response_time",
|
|
Type: v3.AttributeKeyTypeTag,
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
},
|
|
},
|
|
tags: []v3.AttributeKey{
|
|
{Key: "name"},
|
|
{Key: "value"},
|
|
},
|
|
},
|
|
want: "`name` asc,value asc,attributes_string['response_time'] desc",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := orderByAttributeKeyTags(tt.args.panelType, tt.args.items, tt.args.tags); got != tt.want {
|
|
t.Errorf("orderByAttributeKeyTags() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_generateAggregateClause(t *testing.T) {
|
|
type args struct {
|
|
op v3.AggregateOperator
|
|
aggKey string
|
|
step int64
|
|
preferRPM bool
|
|
timeFilter string
|
|
whereClause string
|
|
groupBy string
|
|
having string
|
|
orderBy string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "test rate",
|
|
args: args{
|
|
op: v3.AggregateOperatorRate,
|
|
aggKey: "test",
|
|
step: 60,
|
|
preferRPM: false,
|
|
timeFilter: "(timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458)",
|
|
whereClause: " AND attributes_string['service.name'] = 'test'",
|
|
groupBy: " group by `user_name`",
|
|
having: "",
|
|
orderBy: " order by `user_name` desc",
|
|
},
|
|
want: " count(test)/60.000000 as value from signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
|
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['service.name'] = 'test' " +
|
|
"group by `user_name` order by `user_name` desc",
|
|
},
|
|
{
|
|
name: "test P10 with all args",
|
|
args: args{
|
|
op: v3.AggregateOperatorRate,
|
|
aggKey: "test",
|
|
step: 60,
|
|
preferRPM: false,
|
|
timeFilter: "(timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458)",
|
|
whereClause: " AND attributes_string['service.name'] = 'test'",
|
|
groupBy: " group by `user_name`",
|
|
having: " having value > 10",
|
|
orderBy: " order by `user_name` desc",
|
|
},
|
|
want: " count(test)/60.000000 as value from signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
|
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['service.name'] = 'test' group by `user_name` having value > 10 order by " +
|
|
"`user_name` desc",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := generateAggregateClause(tt.args.op, tt.args.aggKey, tt.args.step, tt.args.preferRPM, tt.args.timeFilter, tt.args.whereClause, tt.args.groupBy, tt.args.having, tt.args.orderBy)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("generateAggreagteClause() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("generateAggreagteClause() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_buildLogsQuery(t *testing.T) {
|
|
type args struct {
|
|
panelType v3.PanelType
|
|
start int64
|
|
end int64
|
|
step int64
|
|
mq *v3.BuilderQuery
|
|
graphLimitQtype string
|
|
preferRPM bool
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "build logs query",
|
|
args: args{
|
|
panelType: v3.PanelTypeTable,
|
|
start: 1680066360726210000,
|
|
end: 1680066458000000000,
|
|
step: 1000,
|
|
mq: &v3.BuilderQuery{
|
|
AggregateOperator: v3.AggregateOperatorCount,
|
|
Filters: &v3.FilterSet{
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
},
|
|
},
|
|
GroupBy: []v3.AttributeKey{
|
|
{
|
|
Key: "user_name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
},
|
|
OrderBy: []v3.OrderBy{
|
|
{
|
|
ColumnName: "user_name",
|
|
Order: "desc",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: "SELECT attributes_string['user_name'] as `user_name`, toFloat64(count(*)) as value from signoz_logs.distributed_logs_v2 " +
|
|
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
|
"AND attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') AND mapContains(attributes_string, 'user_name') " +
|
|
"group by `user_name` order by `user_name` desc",
|
|
},
|
|
{
|
|
name: "build logs query noop",
|
|
args: args{
|
|
panelType: v3.PanelTypeList,
|
|
start: 1680066360726210000,
|
|
end: 1680066458000000000,
|
|
step: 1000,
|
|
mq: &v3.BuilderQuery{
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Filters: &v3.FilterSet{
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
},
|
|
},
|
|
OrderBy: []v3.OrderBy{
|
|
{
|
|
ColumnName: "timestamp",
|
|
Order: "desc",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string " +
|
|
"from signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
|
"AND attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') order by timestamp desc",
|
|
},
|
|
{
|
|
name: "build logs query with all args",
|
|
args: args{
|
|
panelType: v3.PanelTypeGraph,
|
|
start: 1680066360726210000,
|
|
end: 1680066458000000000,
|
|
step: 60,
|
|
mq: &v3.BuilderQuery{
|
|
AggregateOperator: v3.AggregateOperatorAvg,
|
|
AggregateAttribute: v3.AttributeKey{
|
|
Key: "duration",
|
|
Type: v3.AttributeKeyTypeTag,
|
|
DataType: v3.AttributeKeyDataTypeFloat64,
|
|
},
|
|
Filters: &v3.FilterSet{
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "service.name",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
Operator: v3.FilterOperatorEqual,
|
|
Value: "test",
|
|
},
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "duration",
|
|
DataType: v3.AttributeKeyDataTypeFloat64,
|
|
Type: v3.AttributeKeyTypeTag,
|
|
},
|
|
Operator: v3.FilterOperatorGreaterThan,
|
|
Value: 1000,
|
|
},
|
|
},
|
|
},
|
|
GroupBy: []v3.AttributeKey{
|
|
{
|
|
Key: "host",
|
|
DataType: v3.AttributeKeyDataTypeString,
|
|
Type: v3.AttributeKeyTypeResource,
|
|
},
|
|
},
|
|
OrderBy: []v3.OrderBy{
|
|
{
|
|
ColumnName: "host",
|
|
Order: "desc",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, resources_string['host'] as `host`, avg(attributes_number['duration']) as value " +
|
|
"from signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
|
"AND attributes_number['duration'] > 1000.000000 AND mapContains(attributes_number, 'duration') AND mapContains(attributes_number, 'duration') AND " +
|
|
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) " +
|
|
"AND simpleJSONExtractString(labels, 'service.name') = 'test' AND labels like '%service.name%test%' AND ( (simpleJSONHas(labels, 'host') AND labels like '%host%') ))) " +
|
|
"group by `host`,ts order by `host` desc",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := buildLogsQuery(tt.args.panelType, tt.args.start, tt.args.end, tt.args.step, tt.args.mq, tt.args.graphLimitQtype, tt.args.preferRPM)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("buildLogsQuery() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("buildLogsQuery() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPrepareLogsQuery(t *testing.T) {
|
|
type args struct {
|
|
start int64
|
|
end int64
|
|
queryType v3.QueryType
|
|
panelType v3.PanelType
|
|
mq *v3.BuilderQuery
|
|
options v3.LogQBOptions
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "TABLE: Test count with JSON Filter Array, groupBy, orderBy",
|
|
args: args{
|
|
start: 1680066360726210000,
|
|
end: 1680066458000000000,
|
|
panelType: v3.PanelTypeTable,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorCount,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{
|
|
Operator: "AND",
|
|
Items: []v3.FilterItem{
|
|
{
|
|
Key: v3.AttributeKey{
|
|
Key: "body.requestor_list[*]",
|
|
DataType: "array(string)",
|
|
IsJSON: true,
|
|
},
|
|
Operator: "has",
|
|
Value: "index_service",
|
|
},
|
|
},
|
|
},
|
|
GroupBy: []v3.AttributeKey{
|
|
{Key: "name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag},
|
|
{Key: "host", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource},
|
|
},
|
|
OrderBy: []v3.OrderBy{
|
|
{ColumnName: "name", Order: "DESC"},
|
|
},
|
|
},
|
|
},
|
|
want: "SELECT attributes_string['name'] as `name`, resources_string['host'] as `host`, toFloat64(count(*)) as value from signoz_logs.distributed_logs_v2 where " +
|
|
"(timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND lower(body) like lower('%requestor_list%') " +
|
|
"AND lower(body) like lower('%index_service%') AND has(JSONExtract(JSON_QUERY(body, '$.\"requestor_list\"[*]'), 'Array(String)'), 'index_service') AND mapContains(attributes_string, 'name') AND " +
|
|
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
|
"( (simpleJSONHas(labels, 'host') AND labels like '%host%') ))) group by `name`,`host` order by `name` DESC",
|
|
},
|
|
{
|
|
name: "Test TS with limit- first",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeGraph,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateAttribute: v3.AttributeKey{Key: "name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag},
|
|
AggregateOperator: v3.AggregateOperatorCountDistinct,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
|
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "GET", Operator: "="},
|
|
{Key: v3.AttributeKey{Key: "service.name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource}, Value: "app", Operator: "="},
|
|
},
|
|
},
|
|
Limit: 10,
|
|
GroupBy: []v3.AttributeKey{{Key: "user", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
},
|
|
options: v3.LogQBOptions{GraphLimitQtype: constants.FirstQueryGraphLimit, PreferRPM: true},
|
|
},
|
|
want: "SELECT `user` from (SELECT attributes_string['user'] as `user`, toFloat64(count(distinct(attributes_string['name']))) as value from signoz_logs.distributed_logs_v2 " +
|
|
"where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['method'] = 'GET' " +
|
|
"AND mapContains(attributes_string, 'method') AND mapContains(attributes_string, 'user') AND mapContains(attributes_string, 'name') AND (resource_fingerprint GLOBAL IN " +
|
|
"(SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'app' " +
|
|
"AND labels like '%service.name%app%')) group by `user` order by value DESC) LIMIT 10",
|
|
},
|
|
{
|
|
name: "Test TS with limit- second",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeGraph,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateAttribute: v3.AttributeKey{Key: "name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag},
|
|
AggregateOperator: v3.AggregateOperatorCountDistinct,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
|
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "GET", Operator: "="},
|
|
{Key: v3.AttributeKey{Key: "service.name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource}, Value: "app", Operator: "="},
|
|
},
|
|
},
|
|
GroupBy: []v3.AttributeKey{{Key: "user", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
Limit: 2,
|
|
},
|
|
options: v3.LogQBOptions{GraphLimitQtype: constants.SecondQueryGraphLimit},
|
|
},
|
|
want: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string['user'] as `user`, toFloat64(count(distinct(attributes_string['name']))) as value " +
|
|
"from signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND " +
|
|
"attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND mapContains(attributes_string, 'user') AND mapContains(attributes_string, 'name') AND " +
|
|
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
|
"simpleJSONExtractString(labels, 'service.name') = 'app' AND labels like '%service.name%app%')) AND (`user`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `user`,ts order by value DESC",
|
|
},
|
|
{
|
|
name: "Live Tail Query",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
|
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "GET", Operator: "="},
|
|
},
|
|
},
|
|
},
|
|
options: v3.LogQBOptions{IsLivetailQuery: true},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string " +
|
|
"from signoz_logs.distributed_logs_v2 where attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND ",
|
|
},
|
|
{
|
|
name: "Live Tail Query with resource attribute",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
|
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "GET", Operator: "="},
|
|
{Key: v3.AttributeKey{Key: "service.name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource}, Value: "app", Operator: "contains"},
|
|
},
|
|
},
|
|
},
|
|
options: v3.LogQBOptions{IsLivetailQuery: true},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string from " +
|
|
"signoz_logs.distributed_logs_v2 where attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND " +
|
|
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM signoz_logs.distributed_logs_v2_resource WHERE simpleJSONExtractString(lower(labels), 'service.name') LIKE '%app%' AND lower(labels) like '%service.name%app%' AND ",
|
|
},
|
|
{
|
|
name: "Live Tail Query W/O filter",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
|
|
},
|
|
options: v3.LogQBOptions{IsLivetailQuery: true},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string " +
|
|
"from signoz_logs.distributed_logs_v2 where ",
|
|
},
|
|
{
|
|
name: "Table query with limit",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeTable,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorCount,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
|
|
Limit: 10,
|
|
},
|
|
},
|
|
want: "SELECT toFloat64(count(*)) as value from signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) order by value DESC LIMIT 10",
|
|
},
|
|
{
|
|
name: "Test limit less than pageSize - order by ts",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
|
|
OrderBy: []v3.OrderBy{{ColumnName: constants.TIMESTAMP, Order: "desc", Key: constants.TIMESTAMP, DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeUnspecified, IsColumn: true}},
|
|
Limit: 1,
|
|
Offset: 0,
|
|
PageSize: 5,
|
|
},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string from " +
|
|
"signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
|
"order by `timestamp` desc LIMIT 1",
|
|
},
|
|
{
|
|
name: "Test limit greater than pageSize - order by ts",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
|
{Key: v3.AttributeKey{Key: "id", Type: v3.AttributeKeyTypeUnspecified, DataType: v3.AttributeKeyDataTypeString, IsColumn: true}, Operator: v3.FilterOperatorLessThan, Value: "2TNh4vp2TpiWyLt3SzuadLJF2s4"},
|
|
}},
|
|
OrderBy: []v3.OrderBy{{ColumnName: constants.TIMESTAMP, Order: "desc", Key: constants.TIMESTAMP, DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeUnspecified, IsColumn: true}},
|
|
Limit: 100,
|
|
Offset: 10,
|
|
PageSize: 10,
|
|
},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string from " +
|
|
"signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
|
"AND id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by `timestamp` desc LIMIT 10",
|
|
},
|
|
{
|
|
name: "Test limit less than pageSize - order by custom",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
|
|
OrderBy: []v3.OrderBy{{ColumnName: "method", Order: "desc", Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
Limit: 1,
|
|
Offset: 0,
|
|
PageSize: 5,
|
|
},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string from " +
|
|
"signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
|
"order by attributes_string['method'] desc LIMIT 1 OFFSET 0",
|
|
},
|
|
{
|
|
name: "Test limit greater than pageSize - order by custom",
|
|
args: args{
|
|
start: 1680066360726,
|
|
end: 1680066458000,
|
|
queryType: v3.QueryTypeBuilder,
|
|
panelType: v3.PanelTypeList,
|
|
mq: &v3.BuilderQuery{
|
|
QueryName: "A",
|
|
StepInterval: 60,
|
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
|
Expression: "A",
|
|
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
|
{Key: v3.AttributeKey{Key: "id", Type: v3.AttributeKeyTypeUnspecified, DataType: v3.AttributeKeyDataTypeString, IsColumn: true}, Operator: v3.FilterOperatorLessThan, Value: "2TNh4vp2TpiWyLt3SzuadLJF2s4"},
|
|
}},
|
|
OrderBy: []v3.OrderBy{{ColumnName: "method", Order: "desc", Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
|
Limit: 100,
|
|
Offset: 50,
|
|
PageSize: 50,
|
|
},
|
|
},
|
|
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, body, attributes_string, attributes_number, attributes_bool, resources_string from " +
|
|
"signoz_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND " +
|
|
"id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by attributes_string['method'] desc LIMIT 50 OFFSET 50",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := PrepareLogsQuery(tt.args.start, tt.args.end, tt.args.queryType, tt.args.panelType, tt.args.mq, tt.args.options)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("PrepareLogsQuery() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("PrepareLogsQuery() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|