logs-analyzer/signoz/pkg/query-service/app/traces/v3/utils.go
2024-09-02 22:47:30 +03:00

184 lines
4.2 KiB
Go

package v3
import (
"strconv"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/utils"
"go.uber.org/zap"
)
// check if traceId filter is used in traces query and return the list of traceIds
func TraceIdFilterUsedWithEqual(params *v3.QueryRangeParamsV3) (bool, []string) {
compositeQuery := params.CompositeQuery
if compositeQuery == nil {
return false, []string{}
}
var traceIds []string
var traceIdFilterUsed bool
// Build queries for each builder query
for queryName, query := range compositeQuery.BuilderQueries {
if query.Expression != queryName && query.DataSource != v3.DataSourceTraces {
continue
}
// check filter attribute
if query.Filters != nil && len(query.Filters.Items) != 0 {
for _, item := range query.Filters.Items {
if item.Key.Key == "traceID" && (item.Operator == v3.FilterOperatorIn ||
item.Operator == v3.FilterOperatorEqual) {
traceIdFilterUsed = true
// validate value
var err error
val := item.Value
val, err = utils.ValidateAndCastValue(val, item.Key.DataType)
if err != nil {
zap.L().Error("invalid value for key", zap.String("key", item.Key.Key), zap.Error(err))
return false, []string{}
}
if val != nil {
fmtVal := extractFormattedStringValues(val)
traceIds = append(traceIds, fmtVal...)
}
}
}
}
}
zap.L().Debug("traceIds", zap.Any("traceIds", traceIds))
return traceIdFilterUsed, traceIds
}
func extractFormattedStringValues(v interface{}) []string {
// if it's pointer convert it to a value
v = getPointerValue(v)
switch x := v.(type) {
case string:
return []string{x}
case []interface{}:
if len(x) == 0 {
return []string{}
}
switch x[0].(type) {
case string:
values := []string{}
for _, val := range x {
values = append(values, val.(string))
}
return values
default:
return []string{}
}
default:
return []string{}
}
}
func getPointerValue(v interface{}) interface{} {
switch x := v.(type) {
case *uint8:
return *x
case *uint16:
return *x
case *uint32:
return *x
case *uint64:
return *x
case *int:
return *x
case *int8:
return *x
case *int16:
return *x
case *int32:
return *x
case *int64:
return *x
case *float32:
return *x
case *float64:
return *x
case *string:
return *x
case *bool:
return *x
case []interface{}:
values := []interface{}{}
for _, val := range x {
values = append(values, getPointerValue(val))
}
return values
default:
return v
}
}
func AddTimestampFilters(minTime int64, maxTime int64, params *v3.QueryRangeParamsV3) {
if minTime == 0 && maxTime == 0 {
return
}
compositeQuery := params.CompositeQuery
if compositeQuery == nil {
return
}
// Build queries for each builder query
for queryName, query := range compositeQuery.BuilderQueries {
if query.Expression != queryName && query.DataSource != v3.DataSourceTraces {
continue
}
addTimeStampFilter := false
// check filter attribute
if query.Filters != nil && len(query.Filters.Items) != 0 {
for _, item := range query.Filters.Items {
if item.Key.Key == "traceID" && (item.Operator == v3.FilterOperatorIn ||
item.Operator == v3.FilterOperatorEqual) {
addTimeStampFilter = true
}
}
}
// add timestamp filter to query only if traceID filter along with equal/similar operator is used
if addTimeStampFilter {
timeFilters := []v3.FilterItem{
{
Key: v3.AttributeKey{
Key: "timestamp",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
IsColumn: true,
},
Value: strconv.FormatUint(uint64(minTime), 10),
Operator: v3.FilterOperatorGreaterThanOrEq,
},
{
Key: v3.AttributeKey{
Key: "timestamp",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
IsColumn: true,
},
Value: strconv.FormatUint(uint64(maxTime), 10),
Operator: v3.FilterOperatorLessThanOrEq,
},
}
// add new timestamp filter to query
if query.Filters == nil {
query.Filters = &v3.FilterSet{
Items: timeFilters,
}
} else {
query.Filters.Items = append(query.Filters.Items, timeFilters...)
}
}
}
}