2023-09-17 10:40:45 +05:30
package querier
import (
"context"
"fmt"
2023-09-29 18:20:40 +05:30
"strings"
2023-09-17 10:40:45 +05:30
"sync"
logsV3 "go.signoz.io/signoz/pkg/query-service/app/logs/v3"
2024-09-13 17:04:22 +05:30
logsV4 "go.signoz.io/signoz/pkg/query-service/app/logs/v4"
2023-09-17 10:40:45 +05:30
metricsV3 "go.signoz.io/signoz/pkg/query-service/app/metrics/v3"
tracesV3 "go.signoz.io/signoz/pkg/query-service/app/traces/v3"
2024-11-22 12:00:29 +05:30
tracesV4 "go.signoz.io/signoz/pkg/query-service/app/traces/v4"
2024-09-20 19:23:01 +05:30
"go.signoz.io/signoz/pkg/query-service/common"
2023-09-17 10:40:45 +05:30
"go.signoz.io/signoz/pkg/query-service/constants"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
2024-06-12 12:21:27 +05:30
"go.signoz.io/signoz/pkg/query-service/postprocess"
2024-09-20 19:23:01 +05:30
"go.signoz.io/signoz/pkg/query-service/querycache"
2023-09-17 10:40:45 +05:30
"go.uber.org/zap"
)
2024-07-15 18:06:39 +05:30
func prepareLogsQuery ( _ context . Context ,
2024-09-13 17:04:22 +05:30
useLogsNewSchema bool ,
2024-02-12 18:45:21 +05:30
start ,
end int64 ,
builderQuery * v3 . BuilderQuery ,
params * v3 . QueryRangeParamsV3 ,
preferRPM bool ,
) ( string , error ) {
query := ""
2024-09-13 17:04:22 +05:30
logsQueryBuilder := logsV3 . PrepareLogsQuery
if useLogsNewSchema {
logsQueryBuilder = logsV4 . PrepareLogsQuery
}
2024-02-12 18:45:21 +05:30
if params == nil || builderQuery == nil {
return query , fmt . Errorf ( "params and builderQuery cannot be nil" )
}
// for ts query with limit replace it as it is already formed
if params . CompositeQuery . PanelType == v3 . PanelTypeGraph && builderQuery . Limit > 0 && len ( builderQuery . GroupBy ) > 0 {
2024-09-13 17:04:22 +05:30
limitQuery , err := logsQueryBuilder (
2024-02-12 18:45:21 +05:30
start ,
end ,
params . CompositeQuery . QueryType ,
params . CompositeQuery . PanelType ,
builderQuery ,
2024-10-22 16:46:58 +05:30
v3 . QBOptions { GraphLimitQtype : constants . FirstQueryGraphLimit , PreferRPM : preferRPM } ,
2024-02-12 18:45:21 +05:30
)
if err != nil {
return query , err
}
2024-09-13 17:04:22 +05:30
placeholderQuery , err := logsQueryBuilder (
2024-02-12 18:45:21 +05:30
start ,
end ,
params . CompositeQuery . QueryType ,
params . CompositeQuery . PanelType ,
builderQuery ,
2024-10-22 16:46:58 +05:30
v3 . QBOptions { GraphLimitQtype : constants . SecondQueryGraphLimit , PreferRPM : preferRPM } ,
2024-02-12 18:45:21 +05:30
)
if err != nil {
return query , err
}
query = strings . Replace ( placeholderQuery , "#LIMIT_PLACEHOLDER" , limitQuery , 1 )
return query , err
}
2024-09-13 17:04:22 +05:30
query , err := logsQueryBuilder (
2024-02-12 18:45:21 +05:30
start ,
end ,
params . CompositeQuery . QueryType ,
params . CompositeQuery . PanelType ,
builderQuery ,
2024-10-22 16:46:58 +05:30
v3 . QBOptions { PreferRPM : preferRPM } ,
2024-02-12 18:45:21 +05:30
)
if err != nil {
return query , err
}
return query , err
}
2023-09-17 10:40:45 +05:30
func ( q * querier ) runBuilderQuery (
ctx context . Context ,
builderQuery * v3 . BuilderQuery ,
params * v3 . QueryRangeParamsV3 ,
cacheKeys map [ string ] string ,
ch chan channelResult ,
wg * sync . WaitGroup ,
) {
defer wg . Done ( )
queryName := builderQuery . QueryName
var preferRPM bool
if q . featureLookUp != nil {
preferRPM = q . featureLookUp . CheckFeature ( constants . PreferRPM ) == nil
}
2024-03-08 21:12:53 +05:30
start := params . Start
end := params . End
if builderQuery . ShiftBy != 0 {
start = start - builderQuery . ShiftBy * 1000
end = end - builderQuery . ShiftBy * 1000
}
2023-09-17 10:40:45 +05:30
if builderQuery . DataSource == v3 . DataSourceLogs {
var query string
var err error
2024-09-20 19:23:01 +05:30
if _ , ok := cacheKeys [ queryName ] ; ! ok || params . NoCache {
zap . L ( ) . Info ( "skipping cache for logs query" , zap . String ( "queryName" , queryName ) , zap . Int64 ( "start" , start ) , zap . Int64 ( "end" , end ) , zap . Int64 ( "step" , builderQuery . StepInterval ) , zap . Bool ( "noCache" , params . NoCache ) , zap . String ( "cacheKey" , cacheKeys [ queryName ] ) )
2024-09-13 17:04:22 +05:30
query , err = prepareLogsQuery ( ctx , q . UseLogsNewSchema , start , end , builderQuery , params , preferRPM )
2023-09-17 10:40:45 +05:30
if err != nil {
2024-02-12 18:45:21 +05:30
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : nil }
2023-09-17 10:40:45 +05:30
return
}
2024-02-12 18:45:21 +05:30
series , err := q . execClickHouseQuery ( ctx , query )
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : series }
return
}
2024-09-20 19:23:01 +05:30
misses := q . queryCache . FindMissingTimeRanges ( start , end , builderQuery . StepInterval , cacheKeys [ queryName ] )
zap . L ( ) . Info ( "cache misses for logs query" , zap . Any ( "misses" , misses ) )
missedSeries := make ( [ ] querycache . CachedSeriesData , 0 )
2024-02-12 18:45:21 +05:30
for _ , miss := range misses {
2024-09-20 19:23:01 +05:30
query , err = prepareLogsQuery ( ctx , q . UseLogsNewSchema , miss . Start , miss . End , builderQuery , params , preferRPM )
2023-09-17 10:40:45 +05:30
if err != nil {
2024-02-12 18:45:21 +05:30
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : nil }
2023-09-17 10:40:45 +05:30
return
}
2024-02-12 18:45:21 +05:30
series , err := q . execClickHouseQuery ( ctx , query )
2023-09-17 10:40:45 +05:30
if err != nil {
2024-02-12 18:45:21 +05:30
ch <- channelResult {
Err : err ,
Name : queryName ,
Query : query ,
Series : nil ,
}
2023-09-17 10:40:45 +05:30
return
}
2024-09-20 19:23:01 +05:30
missedSeries = append ( missedSeries , querycache . CachedSeriesData {
Start : miss . Start ,
End : miss . End ,
Data : series ,
} )
2023-09-17 10:40:45 +05:30
}
2024-09-20 19:23:01 +05:30
mergedSeries := q . queryCache . MergeWithCachedSeriesData ( cacheKeys [ queryName ] , missedSeries )
2023-09-17 10:40:45 +05:30
2024-09-20 19:23:01 +05:30
resultSeries := common . GetSeriesFromCachedData ( mergedSeries , start , end )
2024-02-12 18:45:21 +05:30
ch <- channelResult {
Err : nil ,
Name : queryName ,
2024-09-20 19:23:01 +05:30
Series : resultSeries ,
2024-02-12 18:45:21 +05:30
}
2023-09-17 10:40:45 +05:30
return
}
if builderQuery . DataSource == v3 . DataSourceTraces {
2024-11-22 12:00:29 +05:30
tracesQueryBuilder := tracesV3 . PrepareTracesQuery
if q . UseTraceNewSchema {
tracesQueryBuilder = tracesV4 . PrepareTracesQuery
}
2023-09-17 10:40:45 +05:30
var query string
var err error
// for ts query with group by and limit form two queries
if params . CompositeQuery . PanelType == v3 . PanelTypeGraph && builderQuery . Limit > 0 && len ( builderQuery . GroupBy ) > 0 {
2024-11-22 12:00:29 +05:30
limitQuery , err := tracesQueryBuilder (
2024-03-08 21:12:53 +05:30
start ,
end ,
2023-09-17 10:40:45 +05:30
params . CompositeQuery . PanelType ,
builderQuery ,
2024-10-22 16:46:58 +05:30
v3 . QBOptions { GraphLimitQtype : constants . FirstQueryGraphLimit , PreferRPM : preferRPM } ,
2023-09-17 10:40:45 +05:30
)
if err != nil {
ch <- channelResult { Err : err , Name : queryName , Query : limitQuery , Series : nil }
return
}
2024-11-22 12:00:29 +05:30
placeholderQuery , err := tracesQueryBuilder (
2024-03-08 21:12:53 +05:30
start ,
end ,
2023-09-17 10:40:45 +05:30
params . CompositeQuery . PanelType ,
builderQuery ,
2024-10-22 16:46:58 +05:30
v3 . QBOptions { GraphLimitQtype : constants . SecondQueryGraphLimit , PreferRPM : preferRPM } ,
2023-09-17 10:40:45 +05:30
)
if err != nil {
ch <- channelResult { Err : err , Name : queryName , Query : limitQuery , Series : nil }
return
}
query = fmt . Sprintf ( placeholderQuery , limitQuery )
} else {
2024-11-22 12:00:29 +05:30
query , err = tracesQueryBuilder (
2024-03-08 21:12:53 +05:30
start ,
end ,
2023-09-17 10:40:45 +05:30
params . CompositeQuery . PanelType ,
builderQuery ,
2024-10-22 16:46:58 +05:30
v3 . QBOptions { PreferRPM : preferRPM } ,
2023-09-17 10:40:45 +05:30
)
if err != nil {
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : nil }
return
}
}
series , err := q . execClickHouseQuery ( ctx , query )
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : series }
return
}
// What is happening here?
// We are only caching the graph panel queries. A non-existant cache key means that the query is not cached.
// If the query is not cached, we execute the query and return the result without caching it.
2024-09-20 19:23:01 +05:30
if _ , ok := cacheKeys [ queryName ] ; ! ok || params . NoCache {
zap . L ( ) . Info ( "skipping cache for metrics query" , zap . String ( "queryName" , queryName ) , zap . Int64 ( "start" , start ) , zap . Int64 ( "end" , end ) , zap . Int64 ( "step" , builderQuery . StepInterval ) , zap . Bool ( "noCache" , params . NoCache ) , zap . String ( "cacheKey" , cacheKeys [ queryName ] ) )
2024-03-08 21:12:53 +05:30
query , err := metricsV3 . PrepareMetricQuery ( start , end , params . CompositeQuery . QueryType , params . CompositeQuery . PanelType , builderQuery , metricsV3 . Options { PreferRPM : preferRPM } )
2023-09-17 10:40:45 +05:30
if err != nil {
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : nil }
return
}
series , err := q . execClickHouseQuery ( ctx , query )
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : series }
return
}
cacheKey := cacheKeys [ queryName ]
2024-09-20 19:23:01 +05:30
misses := q . queryCache . FindMissingTimeRanges ( start , end , builderQuery . StepInterval , cacheKey )
zap . L ( ) . Info ( "cache misses for metrics query" , zap . Any ( "misses" , misses ) )
missedSeries := make ( [ ] querycache . CachedSeriesData , 0 )
2023-09-17 10:40:45 +05:30
for _ , miss := range misses {
query , err := metricsV3 . PrepareMetricQuery (
2024-09-20 19:23:01 +05:30
miss . Start ,
miss . End ,
2023-09-17 10:40:45 +05:30
params . CompositeQuery . QueryType ,
params . CompositeQuery . PanelType ,
builderQuery ,
metricsV3 . Options { } ,
)
if err != nil {
ch <- channelResult {
Err : err ,
Name : queryName ,
Query : query ,
Series : nil ,
}
return
}
series , err := q . execClickHouseQuery ( ctx , query )
if err != nil {
ch <- channelResult {
Err : err ,
Name : queryName ,
Query : query ,
Series : nil ,
}
return
}
2024-09-20 19:23:01 +05:30
missedSeries = append ( missedSeries , querycache . CachedSeriesData {
Start : miss . Start ,
End : miss . End ,
Data : series ,
} )
2024-02-12 18:45:21 +05:30
}
2024-09-20 19:23:01 +05:30
mergedSeries := q . queryCache . MergeWithCachedSeriesData ( cacheKey , missedSeries )
resultSeries := common . GetSeriesFromCachedData ( mergedSeries , start , end )
2023-09-17 10:40:45 +05:30
ch <- channelResult {
Err : nil ,
Name : queryName ,
2024-09-20 19:23:01 +05:30
Series : resultSeries ,
2023-09-17 10:40:45 +05:30
}
}
func ( q * querier ) runBuilderExpression (
ctx context . Context ,
builderQuery * v3 . BuilderQuery ,
params * v3 . QueryRangeParamsV3 ,
cacheKeys map [ string ] string ,
ch chan channelResult ,
wg * sync . WaitGroup ,
) {
defer wg . Done ( )
queryName := builderQuery . QueryName
2024-09-13 16:43:56 +05:30
queries , err := q . builder . PrepareQueries ( params )
2023-09-17 10:40:45 +05:30
if err != nil {
ch <- channelResult { Err : err , Name : queryName , Query : "" , Series : nil }
return
}
2024-09-20 19:23:01 +05:30
if _ , ok := cacheKeys [ queryName ] ; ! ok || params . NoCache {
zap . L ( ) . Info ( "skipping cache for expression query" , zap . String ( "queryName" , queryName ) , zap . Int64 ( "start" , params . Start ) , zap . Int64 ( "end" , params . End ) , zap . Int64 ( "step" , params . Step ) , zap . Bool ( "noCache" , params . NoCache ) , zap . String ( "cacheKey" , cacheKeys [ queryName ] ) )
2023-09-17 10:40:45 +05:30
query := queries [ queryName ]
series , err := q . execClickHouseQuery ( ctx , query )
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : series }
return
}
cacheKey := cacheKeys [ queryName ]
2024-06-12 12:21:27 +05:30
step := postprocess . StepIntervalForFunction ( params , queryName )
2024-09-20 19:23:01 +05:30
misses := q . queryCache . FindMissingTimeRanges ( params . Start , params . End , step , cacheKey )
zap . L ( ) . Info ( "cache misses for expression query" , zap . Any ( "misses" , misses ) )
missedSeries := make ( [ ] querycache . CachedSeriesData , 0 )
2023-09-17 10:40:45 +05:30
for _ , miss := range misses {
missQueries , _ := q . builder . PrepareQueries ( & v3 . QueryRangeParamsV3 {
2024-09-20 19:23:01 +05:30
Start : miss . Start ,
End : miss . End ,
2023-09-17 10:40:45 +05:30
Step : params . Step ,
NoCache : params . NoCache ,
CompositeQuery : params . CompositeQuery ,
Variables : params . Variables ,
2024-09-13 16:43:56 +05:30
} )
2023-09-17 10:40:45 +05:30
query := missQueries [ queryName ]
series , err := q . execClickHouseQuery ( ctx , query )
if err != nil {
ch <- channelResult { Err : err , Name : queryName , Query : query , Series : nil }
return
}
2024-09-20 19:23:01 +05:30
missedSeries = append ( missedSeries , querycache . CachedSeriesData {
Start : miss . Start ,
End : miss . End ,
Data : series ,
} )
2024-09-04 10:35:13 +05:30
}
2024-09-20 19:23:01 +05:30
mergedSeries := q . queryCache . MergeWithCachedSeriesData ( cacheKey , missedSeries )
2023-09-17 10:40:45 +05:30
2024-09-20 19:23:01 +05:30
resultSeries := common . GetSeriesFromCachedData ( mergedSeries , params . Start , params . End )
2024-02-12 18:45:21 +05:30
2023-09-17 10:40:45 +05:30
ch <- channelResult {
Err : nil ,
Name : queryName ,
2024-09-20 19:23:01 +05:30
Series : resultSeries ,
2023-09-17 10:40:45 +05:30
}
}