@@ -30,6 +30,7 @@ export class DataSource
30
30
streamFields : any [ ] ;
31
31
cachedQuery : CachedQuery ;
32
32
timestampColumn : string ;
33
+ histogramQuery : any ;
33
34
34
35
constructor ( instanceSettings : DataSourceInstanceSettings < MyDataSourceOptions > ) {
35
36
super ( instanceSettings ) ;
@@ -43,6 +44,7 @@ export class DataSource
43
44
promise : null ,
44
45
} ;
45
46
this . timestampColumn = instanceSettings . jsonData . timestamp_column ;
47
+ this . histogramQuery = null ;
46
48
}
47
49
48
50
applyTemplateVariables ( query : MyQuery , scopedVars : any ) : MyQuery {
@@ -54,9 +56,14 @@ export class DataSource
54
56
55
57
async query ( options : DataQueryRequest < MyQuery > ) : Promise < DataQueryResponse > {
56
58
const timestamps = getConsumableTime ( options . range ) ;
59
+ // console.log('timestamps', timestamps);
60
+ // console.log('options', options);
57
61
const interpolatedTargets = options . targets . map ( ( target ) => {
58
62
return this . applyTemplateVariables ( target , options . scopedVars ) ;
59
63
} ) ;
64
+
65
+ // console.log("options", options);
66
+
60
67
const promises = interpolatedTargets . map ( ( target ) => {
61
68
if ( ! this . cachedQuery . data ) {
62
69
this . cachedQuery . data = new Promise ( ( resolve , reject ) => {
@@ -66,21 +73,40 @@ export class DataSource
66
73
} ;
67
74
} ) ;
68
75
}
69
- const reqData = buildQuery ( target , timestamps , this . streamFields , options . app , this . timestampColumn ) ;
76
+
77
+ let reqData = buildQuery ( target , timestamps , this . streamFields , options . app , this . timestampColumn ) ;
78
+
79
+ // // If its a logs search query, we need to save the histogram query from the request
80
+ // // We store it in the histogramQuery variable and use it later for the graph query if the request is for a graph
81
+ if ( ! target . refId ?. includes ( REF_ID_STARTER_LOG_VOLUME ) ) {
82
+ this . histogramQuery = reqData ;
83
+ } else if ( target . refId ?. includes ( REF_ID_STARTER_LOG_VOLUME ) && this . histogramQuery ) {
84
+ reqData = this . histogramQuery ;
85
+ reqData . query . sql_mode = 'context' ;
86
+ delete reqData . query . size ;
87
+ }
88
+
70
89
const cacheKey = JSON . stringify ( {
71
90
reqData,
72
91
displayMode : target . displayMode ?? 'auto' ,
92
+ type : target . refId ,
73
93
} ) ;
74
-
94
+
95
+ console . log ( 'cacheKey' , cacheKey ) ;
96
+ console . log ( 'cached request query' , this . cachedQuery ) ;
97
+ console . log ( 'Is same' , this . cachedQuery . requestQuery === cacheKey ) ;
75
98
if ( cacheKey === this . cachedQuery . requestQuery ) {
76
99
return this . cachedQuery . data
77
100
?. then ( ( res ) => {
101
+ console . log ( 'res in cache' , target , res ) ;
78
102
const mode = target . displayMode || 'auto' ;
103
+ // console.log('mode', mode);
104
+ // console.log('res in cache', res);
79
105
if ( target ?. refId ?. includes ( REF_ID_STARTER_LOG_VOLUME ) ) {
80
106
return res . graph ;
81
107
}
82
108
if ( options . app === 'panel-editor' || options . app === 'dashboard' ) {
83
- if ( mode === 'graph' || mode === 'auto' ) {
109
+ if ( mode === 'graph' || mode === 'auto' ) {
84
110
return res . graph ;
85
111
}
86
112
}
@@ -100,24 +126,85 @@ export class DataSource
100
126
this . cachedQuery . isFetching = true ;
101
127
return this . doRequest ( target , reqData )
102
128
. then ( ( response ) => {
103
- if ( options . app === 'panel-editor' || options . app === 'dashboard' ) {
104
- const mode = target . displayMode || 'auto' ;
105
- const logsDf = getLogsDataFrame ( response . hits , target , this . streamFields , this . timestampColumn ) ;
106
- const graphDf = getGraphDataFrame ( response . hits , target , options . app , this . timestampColumn ) ;
107
- this . cachedQuery . promise ?. resolve ( { graph : graphDf , logs : logsDf } ) ;
108
- return mode === 'logs' ? logsDf : graphDf ;
109
- }
129
+ // if (options.app === 'panel-editor' || options.app === 'dashboard') {
130
+ // const mode = target.displayMode || 'auto';
131
+ // const logsDf = getLogsDataFrame(response.hits, target, this.streamFields, this.timestampColumn);
132
+ // const graphDf = getGraphDataFrame(response.hits, target, options.app, this.timestampColumn);
133
+ // this.cachedQuery.promise?.resolve({ graph: graphDf, logs: logsDf });
134
+ // return mode === 'logs' ? logsDf : graphDf;
135
+ // }
136
+
137
+ // Handle histogram queries for log volume using partitions
138
+ if ( target ?. refId ?. includes ( REF_ID_STARTER_LOG_VOLUME ) && this . histogramQuery ) {
139
+ // First, get partition information for histogram queries
140
+ return this . doPartitionRequest ( target , this . histogramQuery . query )
141
+ . then ( ( partitionResponse ) => {
142
+ // Check if partitions are available
143
+ if ( partitionResponse ?. partitions ?. length > 0 ) {
144
+ // Use partitions to make histogram requests
145
+ const partitions = partitionResponse . partitions ;
146
+
147
+ if ( ! partitionResponse . is_histogram_eligible ) {
148
+ return null ;
149
+ }
110
150
111
- const logsDataFrame = getLogsDataFrame ( response . hits , target , this . streamFields , this . timestampColumn ) ;
151
+ const histogramPromises = partitions . map ( ( partition : any ) => {
152
+ // Create histogram query for each partition
153
+ const partitionHistogramQuery = {
154
+ ...this . histogramQuery ,
155
+ query : {
156
+ ...this . histogramQuery . query ,
157
+ start_time : partition [ 0 ] ,
158
+ end_time : partition [ 1 ] ,
159
+ histogram_interval : partitionResponse . histogram_interval ,
160
+ } ,
161
+ } ;
112
162
113
- const graphDataFrame = getGraphDataFrame ( response ?. aggs ?. histogram || [ ] , target , options . app , this . timestampColumn ) ;
163
+ return this . doHistogramRequest ( target , partitionHistogramQuery ) ;
164
+ } ) ;
114
165
115
- this . cachedQuery . promise ?. resolve ( { graph : graphDataFrame , logs : logsDataFrame } ) ;
166
+ // Combine results from all partitions
167
+ return Promise . all ( histogramPromises ) . then ( ( histogramResponses ) => {
168
+ // Merge histogram data from all partitions
169
+ const combinedHits = histogramResponses . reduce ( ( acc , response ) => {
170
+ return acc . concat ( response . hits || [ ] ) ;
171
+ } , [ ] ) ;
116
172
117
- if ( target ?. refId ?. includes ( REF_ID_STARTER_LOG_VOLUME ) ) {
173
+ const graphDataFrame = getGraphDataFrame ( combinedHits , target , options . app , 'zo_sql_key' ) ;
174
+ this . cachedQuery . promise ?. resolve ( { graph : graphDataFrame , logs : null } ) ;
175
+
176
+ return graphDataFrame ;
177
+ } ) ;
178
+ } else {
179
+ // Fallback to direct histogram request if no partitions
180
+ return this . doHistogramRequest ( target , this . histogramQuery ) . then ( ( histogramResponse ) => {
181
+ const graphDataFrame = getGraphDataFrame (
182
+ histogramResponse . hits ,
183
+ target ,
184
+ options . app ,
185
+ this . timestampColumn
186
+ ) ;
187
+ this . cachedQuery . promise ?. resolve ( { graph : graphDataFrame , logs : null } ) ;
188
+ return graphDataFrame ;
189
+ } ) ;
190
+ }
191
+ } )
192
+ . catch ( ( error ) => {
193
+ console . error ( 'Partition or histogram request failed:' , error ) ;
194
+ // Fallback to empty graph
195
+ const graphDataFrame = getGraphDataFrame ( [ ] , target , options . app , this . timestampColumn ) ;
196
+ this . cachedQuery . promise ?. resolve ( { graph : graphDataFrame , logs : null } ) ;
197
+ return graphDataFrame ;
198
+ } ) ;
199
+ } else if ( target ?. refId ?. includes ( REF_ID_STARTER_LOG_VOLUME ) ) {
200
+ const graphDataFrame = getGraphDataFrame ( [ ] , target , options . app , this . timestampColumn ) ;
201
+ this . cachedQuery . promise ?. resolve ( { graph : graphDataFrame , logs : null } ) ;
118
202
return graphDataFrame ;
203
+ } else {
204
+ const logsDataFrame = getLogsDataFrame ( response . hits , target , this . streamFields , this . timestampColumn ) ;
205
+ this . cachedQuery . promise ?. resolve ( { graph : null , logs : logsDataFrame } ) ;
206
+ return logsDataFrame ;
119
207
}
120
- return logsDataFrame ;
121
208
} )
122
209
. catch ( ( err ) => {
123
210
this . cachedQuery . promise ?. reject ( err ) ;
@@ -149,7 +236,41 @@ export class DataSource
149
236
}
150
237
151
238
doRequest ( target : any , data : any ) {
152
- return getBackendSrv ( ) . post ( this . url + `/api/${ target . organization } /_search?type=logs` , data , {
239
+ const searchType = 'ui' ;
240
+ const useCache = true ;
241
+ const pageType = 'logs' ;
242
+
243
+ const url =
244
+ this . url + `/api/${ target . organization } /_search?type=${ pageType } &search_type=${ searchType } &use_cache=${ useCache } ` ;
245
+
246
+ return getBackendSrv ( ) . post ( url , data , {
247
+ showErrorAlert : false ,
248
+ } ) ;
249
+ }
250
+
251
+ doPartitionRequest ( target : any , data : any ) {
252
+ const pageType = 'logs' ;
253
+ const enableAlignHistogram = true ;
254
+
255
+ const url =
256
+ this . url +
257
+ `/api/${ target . organization } /_search_partition?type=${ pageType } &enable_align_histogram=${ enableAlignHistogram } ` ;
258
+
259
+ return getBackendSrv ( ) . post ( url , data , {
260
+ showErrorAlert : false ,
261
+ } ) ;
262
+ }
263
+
264
+ doHistogramRequest ( target : any , data : any ) {
265
+ const searchType = 'ui' ;
266
+ const useCache = true ;
267
+ const pageType = 'logs' ;
268
+
269
+ const url =
270
+ this . url +
271
+ `/api/${ target . organization } /_search?type=${ pageType } &search_type=${ searchType } &use_cache=${ useCache } &is_ui_histogram=true` ;
272
+
273
+ return getBackendSrv ( ) . post ( url , data , {
153
274
showErrorAlert : false ,
154
275
} ) ;
155
276
}
@@ -217,6 +338,8 @@ export class DataSource
217
338
if ( ! this . getSupportedSupplementaryQueryTypes ( ) . includes ( type ) ) {
218
339
return undefined ;
219
340
}
341
+ // console.log('type', type);
342
+ // console.log('request', request);
220
343
221
344
switch ( type ) {
222
345
case SupplementaryQueryType . LogsVolume :
0 commit comments