3030import net .bytebuddy .implementation .bind .annotation .SuperCall ;
3131import org .apache .cassandra .config .CassandraRelevantProperties ;
3232import org .apache .cassandra .config .Config ;
33+ import org .apache .cassandra .db .Keyspace ;
34+ import org .apache .cassandra .db .ReadCommand ;
3335import org .apache .cassandra .db .ReadExecutionController ;
3436import org .apache .cassandra .db .monitoring .MonitoringTask ;
3537import org .apache .cassandra .db .monitoring .MonitoringTaskTest ;
3941import org .apache .cassandra .distributed .api .ICoordinator ;
4042import org .apache .cassandra .distributed .api .IInvokableInstance ;
4143import org .apache .cassandra .distributed .test .TestBaseImpl ;
44+ import org .apache .cassandra .index .SecondaryIndexManager ;
4245import org .apache .cassandra .index .sai .plan .QueryMonitorableExecutionInfo ;
43- import org .apache .cassandra .index .sai .plan .StorageAttachedIndexSearcher ;
4446import org .assertj .core .api .AbstractIterableAssert ;
4547import org .assertj .core .api .Assertions ;
4648import org .assertj .core .api .ListAssert ;
49+ import org .awaitility .Awaitility ;
4750
4851import static net .bytebuddy .matcher .ElementMatchers .named ;
4952import static org .apache .cassandra .utils .MonotonicClock .approxTime ;
@@ -68,18 +71,18 @@ public void testSlowSAIQueryLogger() throws Throwable
6871 .start ()))
6972 {
7073 // create a table with numeric, text and vector indexes
71- cluster .schemaChange (withKeyspace ("CREATE TABLE %s.t (k int, c int, n int, s text, v vector<float, 2>, PRIMARY KEY(k, c))" ));
74+ cluster .schemaChange (withKeyspace ("CREATE TABLE %s.t (k int, c int, n int, s text, v vector<float, 2>, l int, PRIMARY KEY(k, c))" ));
7275 cluster .schemaChange (withKeyspace ("CREATE CUSTOM INDEX ON %s.t (n) USING 'StorageAttachedIndex'" ));
7376 cluster .schemaChange (withKeyspace ("CREATE CUSTOM INDEX ON %s.t (s) USING 'StorageAttachedIndex'" ));
7477 cluster .schemaChange (withKeyspace ("CREATE CUSTOM INDEX ON %s.t (v) USING 'StorageAttachedIndex'" ));
7578
7679 // insert some data
7780 ICoordinator coordinator = cluster .coordinator (1 );
7881 IInvokableInstance node = cluster .get (1 );
79- coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v) VALUES (1, 1, 1, 's_1', [1, 1])" ), ConsistencyLevel .ONE );
80- coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v) VALUES (1, 2, 2, 's_2', [1, 2])" ), ConsistencyLevel .ONE );
81- coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v) VALUES (2, 1, 3, 's_3', [1, 3])" ), ConsistencyLevel .ONE );
82- coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v) VALUES (2, 2, 4, 's_4', [1, 4])" ), ConsistencyLevel .ONE );
82+ coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v, l ) VALUES (1, 1, 1, 's_1', [1, 1], 1 )" ), ConsistencyLevel .ONE );
83+ coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v, l ) VALUES (1, 2, 2, 's_2', [1, 2], 2 )" ), ConsistencyLevel .ONE );
84+ coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v, l ) VALUES (2, 1, 3, 's_3', [1, 3], 3 )" ), ConsistencyLevel .ONE );
85+ coordinator .execute (withKeyspace ("INSERT INTO %s.t (k, c, n, s, v, l ) VALUES (2, 2, 4, 's_4', [1, 4], 4 )" ), ConsistencyLevel .ONE );
8386 node .flush (KEYSPACE );
8487
8588 // test single numeric query
@@ -292,11 +295,27 @@ public void testSlowSAIQueryLogger() throws Throwable
292295 coordinator .execute (annQuery , ConsistencyLevel .ONE );
293296 coordinator .execute (hybridQuery , ConsistencyLevel .ONE );
294297 assertLogsContain (mark , node , "4 operations were slow" );
295- assertLogsDoNotContain (mark , node ,
296- "SAI slow query metrics:" ,
297- "SAI slow query plan:" ,
298- "SAI slowest query metrics:" ,
299- "SAI slowest query plan:" );
298+ assertLogsDoNotContainSAIExecutionInfo (mark , node );
299+ CassandraRelevantProperties .SAI_SLOW_QUERY_LOG_EXECUTION_INFO_ENABLED .setBoolean (true );
300+
301+ // test with a legacy index, there should be no SAI execution info
302+ cluster .schemaChange (withKeyspace ("CREATE INDEX legacy_idx ON %s.t (l)" ));
303+ Awaitility .waitAtMost (1 , TimeUnit .MINUTES ).until (() -> cluster .get (1 ).callOnInstance (() -> {
304+ SecondaryIndexManager sim = Keyspace .open (KEYSPACE ).getColumnFamilyStore ("t" ).indexManager ;
305+ return sim .isIndexQueryable ("legacy_idx" );
306+ }));
307+ mark = node .logs ().mark ();
308+ String legacyIndexQuery = withKeyspace ("SELECT * FROM %s.t WHERE l = 1" );
309+ coordinator .execute (legacyIndexQuery , ConsistencyLevel .ONE );
310+ assertLogsContain (mark , node , "1 operations were slow" , "WHERE l = 1" );
311+ assertLogsDoNotContainSAIExecutionInfo (mark , node );
312+
313+ // test with a regular, non-indexed query, there should be no SAI execution info
314+ mark = node .logs ().mark ();
315+ String regularQuery = withKeyspace ("SELECT * FROM %s.t WHERE k = 1" );
316+ coordinator .execute (regularQuery , ConsistencyLevel .ONE );
317+ assertLogsContain (mark , node , "1 operations were slow" , "WHERE k = 1" );
318+ assertLogsDoNotContainSAIExecutionInfo (mark , node );
300319 }
301320 }
302321
@@ -305,9 +324,13 @@ private static void assertLogsContain(long mark, IInvokableInstance node, String
305324 assertLogs (mark , node , AbstractIterableAssert ::isNotEmpty , lines );
306325 }
307326
308- private static void assertLogsDoNotContain (long mark , IInvokableInstance node , String ... lines )
327+ private static void assertLogsDoNotContainSAIExecutionInfo (long mark , IInvokableInstance node )
309328 {
310- assertLogs (mark , node , AbstractIterableAssert ::isEmpty , lines );
329+ assertLogs (mark , node , AbstractIterableAssert ::isEmpty ,
330+ "SAI slow query metrics:" ,
331+ "SAI slow query plan:" ,
332+ "SAI slowest query metrics:" ,
333+ "SAI slowest query plan:" );
311334 }
312335
313336 private static void assertLogs (long mark , IInvokableInstance node , Consumer <ListAssert <String >> listAssert , String ... lines )
@@ -332,18 +355,19 @@ public static class BB
332355 @ SuppressWarnings ("resource" )
333356 public static void install (ClassLoader classLoader , int node )
334357 {
335- new ByteBuddy ().rebase (StorageAttachedIndexSearcher .class )
336- .method (named ("search " ))
358+ new ByteBuddy ().rebase (ReadCommand .class )
359+ .method (named ("executeLocally " ))
337360 .intercept (MethodDelegation .to (SlowSAIQueryLoggerTest .BB .class ))
338361 .make ()
339362 .load (classLoader , ClassLoadingStrategy .Default .INJECTION );
340363 }
341364
342365 @ SuppressWarnings ("unused" )
343- public static UnfilteredPartitionIterator search (ReadExecutionController executionController ,
344- @ SuperCall Callable <UnfilteredPartitionIterator > zuper )
366+ public static UnfilteredPartitionIterator executeLocally (ReadExecutionController executionController ,
367+ @ SuperCall Callable <UnfilteredPartitionIterator > zuper )
345368 {
346- Uninterruptibles .sleepUninterruptibly (queryDelay .get (), TimeUnit .MILLISECONDS );
369+ if (executionController .metadata ().keyspace .equals (KEYSPACE ))
370+ Uninterruptibles .sleepUninterruptibly (queryDelay .get (), TimeUnit .MILLISECONDS );
347371 try
348372 {
349373 return zuper .call ();
0 commit comments