mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-30 05:41:58 +08:00
104 lines
3.8 KiB
Go
104 lines
3.8 KiB
Go
package telemetrylogs
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
|
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
|
"github.com/SigNoz/signoz/pkg/valuer"
|
|
)
|
|
|
|
func parseStrValue(valueStr string, operator qbtypes.FilterOperator) (telemetrytypes.FieldDataType, any) {
|
|
|
|
valueType := telemetrytypes.FieldDataTypeString
|
|
|
|
// return the value as is for the following operators
|
|
// as they are always string
|
|
if operator == qbtypes.FilterOperatorContains || operator == qbtypes.FilterOperatorNotContains ||
|
|
operator == qbtypes.FilterOperatorRegexp || operator == qbtypes.FilterOperatorNotRegexp ||
|
|
operator == qbtypes.FilterOperatorLike || operator == qbtypes.FilterOperatorNotLike ||
|
|
operator == qbtypes.FilterOperatorILike || operator == qbtypes.FilterOperatorNotILike {
|
|
return valueType, valueStr
|
|
}
|
|
|
|
var err error
|
|
var parsedValue any
|
|
if parsedValue, err = strconv.ParseBool(valueStr); err == nil {
|
|
valueType = telemetrytypes.FieldDataTypeBool
|
|
} else if parsedValue, err = strconv.ParseInt(valueStr, 10, 64); err == nil {
|
|
valueType = telemetrytypes.FieldDataTypeInt64
|
|
} else if parsedValue, err = strconv.ParseFloat(valueStr, 64); err == nil {
|
|
valueType = telemetrytypes.FieldDataTypeFloat64
|
|
} else {
|
|
parsedValue = valueStr
|
|
valueType = telemetrytypes.FieldDataTypeString
|
|
}
|
|
|
|
return valueType, parsedValue
|
|
}
|
|
|
|
func inferDataType(value any, operator qbtypes.FilterOperator, key *telemetrytypes.TelemetryFieldKey) (telemetrytypes.FieldDataType, any) {
|
|
// check if the value is a int, float, string, bool
|
|
valueType := telemetrytypes.FieldDataTypeUnspecified
|
|
switch v := value.(type) {
|
|
case []any:
|
|
// take the first element and infer the type
|
|
if len(v) > 0 {
|
|
valueType, _ = inferDataType(v[0], operator, key)
|
|
}
|
|
return valueType, v
|
|
case uint8, uint16, uint32, uint64, int, int8, int16, int32, int64:
|
|
valueType = telemetrytypes.FieldDataTypeInt64
|
|
case float32, float64:
|
|
valueType = telemetrytypes.FieldDataTypeFloat64
|
|
case string:
|
|
valueType, value = parseStrValue(v, operator)
|
|
case bool:
|
|
valueType = telemetrytypes.FieldDataTypeBool
|
|
}
|
|
|
|
// check if it is array
|
|
if strings.HasSuffix(key.Name, "[*]") {
|
|
valueType = telemetrytypes.FieldDataType{String: valuer.NewString(fmt.Sprintf("[]%s", valueType.StringValue()))}
|
|
}
|
|
|
|
return valueType, value
|
|
}
|
|
|
|
func getBodyJSONPath(key *telemetrytypes.TelemetryFieldKey) string {
|
|
parts := strings.Split(key.Name, ".")[1:]
|
|
newParts := []string{}
|
|
for _, part := range parts {
|
|
if strings.HasSuffix(part, "[*]") {
|
|
newParts = append(newParts, fmt.Sprintf(`"%s"[*]`, strings.TrimSuffix(part, "[*]")))
|
|
} else {
|
|
newParts = append(newParts, fmt.Sprintf(`"%s"`, part))
|
|
}
|
|
}
|
|
return strings.Join(newParts, ".")
|
|
}
|
|
|
|
func GetBodyJSONKey(_ context.Context, key *telemetrytypes.TelemetryFieldKey, operator qbtypes.FilterOperator, value any) (string, any) {
|
|
|
|
dataType, value := inferDataType(value, operator, key)
|
|
|
|
// for array types, we need to extract the value from the JSON_QUERY
|
|
if dataType == telemetrytypes.FieldDataTypeArrayInt64 ||
|
|
dataType == telemetrytypes.FieldDataTypeArrayFloat64 ||
|
|
dataType == telemetrytypes.FieldDataTypeArrayString ||
|
|
dataType == telemetrytypes.FieldDataTypeArrayBool ||
|
|
dataType == telemetrytypes.FieldDataTypeArrayNumber {
|
|
return fmt.Sprintf("JSONExtract(JSON_QUERY(body, '$.%s'), '%s')", getBodyJSONPath(key), dataType.CHDataType()), value
|
|
}
|
|
|
|
// for all other types, we need to extract the value from the JSON_VALUE
|
|
return fmt.Sprintf("JSONExtract(JSON_VALUE(body, '$.%s'), '%s')", getBodyJSONPath(key), dataType.CHDataType()), value
|
|
}
|
|
|
|
func GetBodyJSONKeyForExists(_ context.Context, key *telemetrytypes.TelemetryFieldKey, _ qbtypes.FilterOperator, _ any) string {
|
|
return fmt.Sprintf("JSON_EXISTS(body, '$.%s')", getBodyJSONPath(key))
|
|
}
|