13
13
*/
14
14
package org .codice .ddf .catalog .ui .util ;
15
15
16
+ import static ddf .catalog .Constants .QUERY_LOGGER_NAME ;
17
+ import static ddf .catalog .impl .operations .QueryOperations .QM_DO_QUERY ;
18
+ import static ddf .catalog .impl .operations .QueryOperations .QM_POST_QUERY ;
19
+ import static ddf .catalog .impl .operations .QueryOperations .QM_PRE_QUERY ;
20
+ import static ddf .catalog .impl .operations .QueryOperations .QM_TIMED_SOURCE ;
21
+ import static ddf .catalog .impl .operations .QueryOperations .QM_TOTAL_ELAPSED ;
22
+ import static java .time .ZoneOffset .UTC ;
23
+ import static java .time .format .DateTimeFormatter .ISO_DATE_TIME ;
24
+
16
25
import com .google .common .base .Stopwatch ;
17
26
import com .google .gson .Gson ;
18
27
import com .google .gson .GsonBuilder ;
54
63
import org .codice .ddf .catalog .ui .query .utility .Status ;
55
64
import org .codice .ddf .catalog .ui .transformer .TransformerDescriptors ;
56
65
import org .codice .gsonsupport .GsonTypeAdapters ;
66
+ import org .slf4j .Logger ;
67
+ import org .slf4j .LoggerFactory ;
57
68
58
69
public class CqlQueriesImpl implements CqlQueries {
59
70
71
+ private static final Logger QUERY_LOGGER = LoggerFactory .getLogger (QUERY_LOGGER_NAME );
72
+
60
73
private final CatalogFramework catalogFramework ;
61
74
62
75
private final FilterBuilder filterBuilder ;
@@ -69,6 +82,8 @@ public class CqlQueriesImpl implements CqlQueries {
69
82
70
83
private static final String METRICS_SOURCE_ELAPSED_PREFIX = "metrics.source.elapsed." ;
71
84
85
+ private static final String CACHE_SOURCES_KEY = "cache-sources" ;
86
+
72
87
private static final Gson GSON =
73
88
new GsonBuilder ()
74
89
.disableHtmlEscaping ()
@@ -92,6 +107,8 @@ public CqlQueriesImpl(
92
107
public CqlQueryResponse executeCqlQuery (CqlRequest cqlRequest )
93
108
throws UnsupportedQueryException , SourceUnavailableException , FederationException ,
94
109
CqlParseException {
110
+ long start = System .nanoTime ();
111
+ String startTime = (new Date ()).toInstant ().atOffset (UTC ).format (ISO_DATE_TIME );
95
112
QueryRequest request = cqlRequest .createQueryRequest (catalogFramework .getId (), filterBuilder );
96
113
Stopwatch stopwatch = Stopwatch .createStarted ();
97
114
@@ -194,6 +211,12 @@ public CqlQueryResponse executeCqlQuery(CqlRequest cqlRequest)
194
211
properties ,
195
212
processingDetails );
196
213
214
+ if (!responses .isEmpty ()) {
215
+ responses .get (0 ).getProperties ().put ("start-time" , startTime );
216
+ responses .get (0 ).getProperties ().put (QM_TOTAL_ELAPSED , System .nanoTime () - start );
217
+ QUERY_LOGGER .info ("QueryMetrics: {}" , getQueryMetricsLog (responses ));
218
+ }
219
+
197
220
return new CqlQueryResponseImpl (
198
221
cqlRequest .getId (),
199
222
request ,
@@ -205,6 +228,75 @@ public CqlQueryResponse executeCqlQuery(CqlRequest cqlRequest)
205
228
descriptors );
206
229
}
207
230
231
+ private Map <String , Serializable > collectQueryProperties (
232
+ Map <String , Serializable > requestProps , Map <String , Serializable > responseProps ) {
233
+ Map <String , Serializable > allProperties = new HashMap <>();
234
+ if (requestProps != null ) {
235
+ allProperties .putAll (requestProps );
236
+ }
237
+ if (responseProps != null ) {
238
+ allProperties .putAll (responseProps );
239
+ }
240
+ return allProperties ;
241
+ }
242
+
243
+ private String getQueryMetricsLog (List <QueryResponse > queryResponses ) {
244
+ Map <String , Serializable > metricsMap = new HashMap <>();
245
+ metricsMap .put ("start-time" , queryResponses .get (0 ).getProperties ().get ("start-time" ));
246
+ for (QueryResponse queryResponse : queryResponses ) {
247
+ Map <String , Serializable > requestProperties =
248
+ queryResponse .getRequest () == null ? null : queryResponse .getRequest ().getProperties ();
249
+ Map <String , Serializable > properties =
250
+ collectQueryProperties (requestProperties , queryResponse .getProperties ());
251
+ // Combine the request and response metrics to log
252
+
253
+ addMetric (metricsMap , "total-duration" , properties .get (QM_TOTAL_ELAPSED ));
254
+ addMetric (metricsMap , "prequery-duration" , properties .get (QM_PRE_QUERY ));
255
+ addMetric (metricsMap , "query-duration" , properties .get (QM_DO_QUERY ));
256
+ addMetric (metricsMap , "postquery-duration" , properties .get (QM_POST_QUERY ));
257
+ HashMap <String , Serializable > sourceDurationMap = new HashMap <>();
258
+ properties
259
+ .entrySet ()
260
+ .stream ()
261
+ .filter (e -> e .getKey () != null && e .getKey ().startsWith (QM_TIMED_SOURCE ))
262
+ .forEach (e -> sourceDurationMap .put (e .getKey ().split (QM_TIMED_SOURCE )[1 ], e .getValue ()));
263
+ Serializable cacheSourceValue = sourceDurationMap .remove ("cache" );
264
+ if (cacheSourceValue != null ) {
265
+ String sourceName = properties .get (CACHE_SOURCES_KEY ).toString ();
266
+ sourceDurationMap .put (sourceName == null ? "Unknown Source" : sourceName , cacheSourceValue );
267
+ }
268
+ Map <String , Serializable > oldSourceDurationMap =
269
+ (Map <String , Serializable >) metricsMap .remove ("source-duration" );
270
+ if (oldSourceDurationMap != null ) {
271
+ oldSourceDurationMap .forEach ((key , value ) -> addMetric (sourceDurationMap , key , value ));
272
+ }
273
+ metricsMap .put ("source-duration" , sourceDurationMap );
274
+ }
275
+
276
+ HashMap <String , Serializable > additionalQueryMetrics =
277
+ (HashMap <String , Serializable >)
278
+ queryResponses .get (0 ).getProperties ().get ("additional-query-metrics" );
279
+ if (additionalQueryMetrics != null ) {
280
+ metricsMap .putAll (additionalQueryMetrics );
281
+ }
282
+
283
+ Gson gson = new GsonBuilder ().disableHtmlEscaping ().create ();
284
+ return gson .toJson (metricsMap );
285
+ }
286
+
287
+ private void addMetric (
288
+ Map <String , Serializable > metricsMap , String metricName , Serializable metricValue ) {
289
+ if (metricValue == null ) {
290
+ return ;
291
+ }
292
+ Serializable oldMetricValue = metricsMap .remove (metricName );
293
+ if (oldMetricValue != null ) {
294
+ metricsMap .put (metricName , (long ) metricValue + (long ) oldMetricValue );
295
+ }
296
+
297
+ metricsMap .put (metricName , metricValue );
298
+ }
299
+
208
300
private List <Result > retrieveHitCount (QueryRequest request , List <QueryResponse > responses )
209
301
throws UnsupportedQueryException , SourceUnavailableException , FederationException {
210
302
QueryResponse queryResponse = catalogFramework .query (request );
0 commit comments