View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.namequeues;
21  
22  import com.google.protobuf.ByteString;
23  import com.google.protobuf.Message;
24  import java.lang.reflect.Constructor;
25  import java.util.ArrayList;
26  import java.util.List;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.HBaseTestingUtility;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.Waiter;
31  import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest;
32  import org.apache.hadoop.hbase.namequeues.response.NamedQueueGetResponse;
33  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
34  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
35  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
36  import org.apache.hadoop.hbase.protobuf.generated.TooSlowLog;
37  import org.apache.hadoop.hbase.testclassification.MasterTests;
38  import org.apache.hadoop.hbase.testclassification.MediumTests;
39  import org.junit.Assert;
40  import org.junit.Test;
41  import org.junit.experimental.categories.Category;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  /**
46   * Tests for Online SlowLog Provider Service
47   */
48  @Category({MasterTests.class, MediumTests.class})
49  public class TestNamedQueueRecorder {
50  
51    private static final Logger LOG = LoggerFactory.getLogger(TestNamedQueueRecorder.class);
52  
53    private static final HBaseTestingUtility HBASE_TESTING_UTILITY = new HBaseTestingUtility();
54  
55    private NamedQueueRecorder namedQueueRecorder;
56  
57    private static int i = 0;
58  
59    private static Configuration applySlowLogRecorderConf(int eventSize) {
60      Configuration conf = HBASE_TESTING_UTILITY.getConfiguration();
61      conf.setBoolean(HConstants.SLOW_LOG_BUFFER_ENABLED_KEY, true);
62      conf.setInt("hbase.regionserver.slowlog.ringbuffer.size", eventSize);
63      return conf;
64    }
65  
66    /**
67     * confirm that for a ringbuffer of slow logs, payload on given index of buffer
68     * has expected elements
69     *
70     * @param i index of ringbuffer logs
71     * @param j data value that was put on index i
72     * @param slowLogPayloads list of payload retrieved from {@link NamedQueueRecorder}
73     * @return if actual values are as per expectations
74     */
75    private boolean confirmPayloadParams(int i, int j,
76        List<TooSlowLog.SlowLogPayload> slowLogPayloads) {
77      boolean isClientExpected = slowLogPayloads.get(i).getClientAddress().equals("client_" + j);
78      boolean isUserExpected = slowLogPayloads.get(i).getUserName().equals("userName_" + j);
79      boolean isClassExpected = slowLogPayloads.get(i).getServerClass().equals("class_" + j);
80      return isClassExpected && isClientExpected && isUserExpected;
81    }
82  
83    @Test
84    public void testOnlieSlowLogConsumption() throws Exception{
85      Configuration conf = applySlowLogRecorderConf(8);
86      Constructor<NamedQueueRecorder> constructor =
87        NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
88      constructor.setAccessible(true);
89      namedQueueRecorder = constructor.newInstance(conf);
90      final AdminProtos.SlowLogResponseRequest request =
91        AdminProtos.SlowLogResponseRequest.newBuilder().setLimit(15).build();
92      namedQueueRecorder.clearNamedQueue(NamedQueuePayload.NamedQueueEvent.SLOW_LOG);
93      Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
94      LOG.debug("Initially ringbuffer of Slow Log records is empty");
95      int i = 0;
96      // add 5 records initially
97      for (; i < 5; i++) {
98        RpcLogDetails rpcLogDetails =
99          getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
100       namedQueueRecorder.addRecord(rpcLogDetails);
101     }
102     Assert.assertNotEquals(-1,
103       HBASE_TESTING_UTILITY.waitFor(3000, new Waiter.Predicate<Exception>() {
104         @Override
105         public boolean evaluate() throws Exception {
106           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 5;
107         }
108       }));
109     List<TooSlowLog.SlowLogPayload> slowLogPayloads = getSlowLogPayloads(request);
110     Assert.assertTrue(confirmPayloadParams(0, 5, slowLogPayloads));
111     Assert.assertTrue(confirmPayloadParams(1, 4, slowLogPayloads));
112     Assert.assertTrue(confirmPayloadParams(2, 3, slowLogPayloads));
113     Assert.assertTrue(confirmPayloadParams(3, 2, slowLogPayloads));
114     Assert.assertTrue(confirmPayloadParams(4, 1, slowLogPayloads));
115     for (; i < 7; i++) {
116       RpcLogDetails rpcLogDetails =
117         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
118       namedQueueRecorder.addRecord(rpcLogDetails);
119     }
120     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
121       new Waiter.Predicate<Exception>() {
122         @Override
123         public boolean evaluate() throws Exception {
124           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 7;
125         }
126       }));
127     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
128       new Waiter.Predicate<Exception>() {
129         @Override
130         public boolean evaluate() throws Exception {
131           List<TooSlowLog.SlowLogPayload> slowLogPayloadsList =
132             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
133           return slowLogPayloadsList.size() == 7 && TestNamedQueueRecorder.this
134             .confirmPayloadParams(0, 7, slowLogPayloadsList) && TestNamedQueueRecorder.this
135             .confirmPayloadParams(5, 2, slowLogPayloadsList) && TestNamedQueueRecorder.this
136             .confirmPayloadParams(6, 1, slowLogPayloadsList);
137         }
138       })
139     );
140     // add 3 more records
141     for (; i < 10; i++) {
142       RpcLogDetails rpcLogDetails =
143         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
144       namedQueueRecorder.addRecord(rpcLogDetails);
145     }
146     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
147       new Waiter.Predicate<Exception>() {
148         @Override
149         public boolean evaluate() throws Exception {
150           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 8;
151         }
152       }));
153     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
154       new Waiter.Predicate<Exception>() {
155         @Override
156         public boolean evaluate() throws Exception {
157           List<TooSlowLog.SlowLogPayload> slowLogPayloadsList =
158             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
159           // confirm ringbuffer is full
160           return slowLogPayloadsList.size() == 8 && TestNamedQueueRecorder.this
161             .confirmPayloadParams(7, 3, slowLogPayloadsList) && TestNamedQueueRecorder.this
162             .confirmPayloadParams(0, 10, slowLogPayloadsList) && TestNamedQueueRecorder.this
163             .confirmPayloadParams(1, 9, slowLogPayloadsList);
164         }
165       })
166     );
167     // add 4 more records
168     for (; i < 14; i++) {
169       RpcLogDetails rpcLogDetails =
170         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
171       namedQueueRecorder.addRecord(rpcLogDetails);
172     }
173     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
174       new Waiter.Predicate<Exception>() {
175         @Override
176         public boolean evaluate() throws Exception {
177           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 8;
178         }
179       }));
180     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
181       new Waiter.Predicate<Exception>() {
182         @Override
183         public boolean evaluate() throws Exception {
184           List<TooSlowLog.SlowLogPayload> slowLogPayloadsList =
185             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
186           return slowLogPayloadsList.size() == 8 && TestNamedQueueRecorder.this
187             .confirmPayloadParams(0, 14, slowLogPayloadsList) && TestNamedQueueRecorder.this
188             .confirmPayloadParams(1, 13, slowLogPayloadsList) && TestNamedQueueRecorder.this
189             .confirmPayloadParams(2, 12, slowLogPayloadsList) && TestNamedQueueRecorder.this
190             .confirmPayloadParams(3, 11, slowLogPayloadsList);
191         }
192       })
193     );
194     final AdminProtos.SlowLogResponseRequest largeLogRequest =
195       AdminProtos.SlowLogResponseRequest.newBuilder()
196         .setLimit(15)
197         .setLogType(AdminProtos.SlowLogResponseRequest.LogType.LARGE_LOG)
198         .build();
199     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
200       new Waiter.Predicate<Exception>() {
201         @Override
202         public boolean evaluate() throws Exception {
203           List<TooSlowLog.SlowLogPayload> slowLogPayloadsList =
204             TestNamedQueueRecorder.this.getSlowLogPayloads(largeLogRequest);
205           return slowLogPayloadsList.size() == 8 && TestNamedQueueRecorder.this
206             .confirmPayloadParams(0, 14, slowLogPayloadsList) && TestNamedQueueRecorder.this
207             .confirmPayloadParams(1, 13, slowLogPayloadsList) && TestNamedQueueRecorder.this
208             .confirmPayloadParams(2, 12, slowLogPayloadsList) && TestNamedQueueRecorder.this
209             .confirmPayloadParams(3, 11, slowLogPayloadsList);
210         }
211       })
212     );
213     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
214       new Waiter.Predicate<Exception>() {
215         @Override
216         public boolean evaluate() throws Exception {
217           boolean isRingBufferCleaned =
218             namedQueueRecorder.clearNamedQueue(NamedQueuePayload.NamedQueueEvent.SLOW_LOG);
219           LOG.debug("cleared the ringbuffer of Online Slow Log records");
220           List<TooSlowLog.SlowLogPayload> slowLogPayloadsList =
221             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
222           return slowLogPayloadsList.size() == 0 && isRingBufferCleaned;
223         }
224       })
225     );
226   }
227 
228   private List<TooSlowLog.SlowLogPayload> getSlowLogPayloads(
229       AdminProtos.SlowLogResponseRequest request) {
230     NamedQueueGetRequest namedQueueGetRequest = new NamedQueueGetRequest();
231     namedQueueGetRequest.setNamedQueueEvent(RpcLogDetails.SLOW_LOG_EVENT);
232     namedQueueGetRequest.setSlowLogResponseRequest(request);
233     NamedQueueGetResponse namedQueueGetResponse =
234       namedQueueRecorder.getNamedQueueRecords(namedQueueGetRequest);
235     return namedQueueGetResponse == null ? new ArrayList<TooSlowLog.SlowLogPayload>()
236       : namedQueueGetResponse.getSlowLogPayloads();
237   }
238 
239   @Test
240   public void testOnlineSlowLogWithHighRecords() throws Exception {
241 
242     Configuration conf = applySlowLogRecorderConf(14);
243     Constructor<NamedQueueRecorder> constructor =
244       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
245     constructor.setAccessible(true);
246     namedQueueRecorder = constructor.newInstance(conf);
247     final AdminProtos.SlowLogResponseRequest request =
248       AdminProtos.SlowLogResponseRequest.newBuilder().setLimit(14 * 11).build();
249 
250     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
251     LOG.debug("Initially ringbuffer of Slow Log records is empty");
252 
253     for (int i = 0; i < 14 * 11; i++) {
254       RpcLogDetails rpcLogDetails =
255         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
256       namedQueueRecorder.addRecord(rpcLogDetails);
257     }
258     LOG.debug("Added 14 * 11 records, ringbuffer should only provide latest 14 records");
259 
260     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
261       new Waiter.Predicate<Exception>() {
262         @Override
263         public boolean evaluate() throws Exception {
264           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 14;
265         }
266       }));
267 
268     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
269       new Waiter.Predicate<Exception>() {
270         @Override
271         public boolean evaluate() throws Exception {
272           List<TooSlowLog.SlowLogPayload> slowLogPayloads =
273             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
274 
275           // confirm strict order of slow log payloads
276           return slowLogPayloads.size() == 14 && TestNamedQueueRecorder.this
277             .confirmPayloadParams(0, 154, slowLogPayloads) && TestNamedQueueRecorder.this
278             .confirmPayloadParams(1, 153, slowLogPayloads) && TestNamedQueueRecorder.this
279             .confirmPayloadParams(2, 152, slowLogPayloads) && TestNamedQueueRecorder.this
280             .confirmPayloadParams(3, 151, slowLogPayloads) && TestNamedQueueRecorder.this
281             .confirmPayloadParams(4, 150, slowLogPayloads) && TestNamedQueueRecorder.this
282             .confirmPayloadParams(5, 149, slowLogPayloads) && TestNamedQueueRecorder.this
283             .confirmPayloadParams(6, 148, slowLogPayloads) && TestNamedQueueRecorder.this
284             .confirmPayloadParams(7, 147, slowLogPayloads) && TestNamedQueueRecorder.this
285             .confirmPayloadParams(8, 146, slowLogPayloads) && TestNamedQueueRecorder.this
286             .confirmPayloadParams(9, 145, slowLogPayloads) && TestNamedQueueRecorder.this
287             .confirmPayloadParams(10, 144, slowLogPayloads) && TestNamedQueueRecorder.this
288             .confirmPayloadParams(11, 143, slowLogPayloads) && TestNamedQueueRecorder.this
289             .confirmPayloadParams(12, 142, slowLogPayloads) && TestNamedQueueRecorder.this
290             .confirmPayloadParams(13, 141, slowLogPayloads);
291         }
292       })
293     );
294 
295     boolean isRingBufferCleaned = namedQueueRecorder.clearNamedQueue(
296       NamedQueuePayload.NamedQueueEvent.SLOW_LOG);
297     Assert.assertTrue(isRingBufferCleaned);
298     LOG.debug("cleared the ringbuffer of Online Slow Log records");
299     List<TooSlowLog.SlowLogPayload> slowLogPayloads = getSlowLogPayloads(request);
300 
301     // confirm ringbuffer is empty
302     Assert.assertEquals(slowLogPayloads.size(), 0);
303   }
304 
305   @Test
306   public void testOnlineSlowLogWithDefaultDisableConfig() throws Exception {
307     Configuration conf = HBASE_TESTING_UTILITY.getConfiguration();
308     conf.unset(HConstants.SLOW_LOG_BUFFER_ENABLED_KEY);
309 
310     Constructor<NamedQueueRecorder> constructor =
311       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
312     constructor.setAccessible(true);
313     namedQueueRecorder = constructor.newInstance(conf);
314     final AdminProtos.SlowLogResponseRequest request =
315       AdminProtos.SlowLogResponseRequest.newBuilder().build();
316     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
317     LOG.debug("Initially ringbuffer of Slow Log records is empty");
318     for (int i = 0; i < 300; i++) {
319       RpcLogDetails rpcLogDetails =
320         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
321       namedQueueRecorder.addRecord(rpcLogDetails);
322     }
323     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
324       new Waiter.Predicate<Exception>() {
325         @Override
326         public boolean evaluate() throws Exception {
327           List<TooSlowLog.SlowLogPayload> slowLogPayloads =
328             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
329           return slowLogPayloads.size() == 0;
330         }
331       })
332     );
333 
334   }
335 
336   @Test
337   public void testOnlineSlowLogWithDisableConfig() throws Exception {
338     Configuration conf = HBASE_TESTING_UTILITY.getConfiguration();
339     conf.setBoolean(HConstants.SLOW_LOG_BUFFER_ENABLED_KEY, false);
340     Constructor<NamedQueueRecorder> constructor =
341       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
342     constructor.setAccessible(true);
343     namedQueueRecorder = constructor.newInstance(conf);
344 
345     final AdminProtos.SlowLogResponseRequest request =
346       AdminProtos.SlowLogResponseRequest.newBuilder().build();
347     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
348     LOG.debug("Initially ringbuffer of Slow Log records is empty");
349     for (int i = 0; i < 300; i++) {
350       RpcLogDetails rpcLogDetails =
351         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
352       namedQueueRecorder.addRecord(rpcLogDetails);
353     }
354     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
355       new Waiter.Predicate<Exception>() {
356         @Override
357         public boolean evaluate() throws Exception {
358           List<TooSlowLog.SlowLogPayload> slowLogPayloads =
359             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
360           return slowLogPayloads.size() == 0;
361         }
362       })
363     );
364     conf.setBoolean(HConstants.SLOW_LOG_BUFFER_ENABLED_KEY, true);
365   }
366 
367   @Test
368   public void testSlowLogFilters() throws Exception {
369 
370     Configuration conf = applySlowLogRecorderConf(30);
371     Constructor<NamedQueueRecorder> constructor =
372       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
373     constructor.setAccessible(true);
374     namedQueueRecorder = constructor.newInstance(conf);
375     final AdminProtos.SlowLogResponseRequest request =
376       AdminProtos.SlowLogResponseRequest.newBuilder()
377         .setLimit(15)
378         .setUserName("userName_87")
379         .build();
380 
381     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
382 
383     LOG.debug("Initially ringbuffer of Slow Log records is empty");
384 
385     for (int i = 0; i < 100; i++) {
386       RpcLogDetails rpcLogDetails =
387         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
388       namedQueueRecorder.addRecord(rpcLogDetails);
389     }
390     LOG.debug("Added 100 records, ringbuffer should only 1 record with matching filter");
391 
392     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
393       new Waiter.Predicate<Exception>() {
394         @Override
395         public boolean evaluate() throws Exception {
396           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 1;
397         }
398       }));
399 
400     final AdminProtos.SlowLogResponseRequest requestClient =
401       AdminProtos.SlowLogResponseRequest.newBuilder()
402         .setLimit(15)
403         .setClientAddress("client_85")
404         .build();
405     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
406       new Waiter.Predicate<Exception>() {
407         @Override
408         public boolean evaluate() throws Exception {
409           return TestNamedQueueRecorder.this.getSlowLogPayloads(requestClient).size() == 1;
410         }
411       }));
412 
413     final AdminProtos.SlowLogResponseRequest requestSlowLog =
414       AdminProtos.SlowLogResponseRequest.newBuilder()
415         .setLimit(15)
416         .build();
417     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
418       new Waiter.Predicate<Exception>() {
419         @Override
420         public boolean evaluate() throws Exception {
421           return TestNamedQueueRecorder.this.getSlowLogPayloads(requestSlowLog).size() == 15;
422         }
423       }));
424   }
425 
426   @Test
427   public void testConcurrentSlowLogEvents() throws Exception {
428 
429     Configuration conf = applySlowLogRecorderConf(50000);
430     Constructor<NamedQueueRecorder> constructor =
431       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
432     constructor.setAccessible(true);
433     namedQueueRecorder = constructor.newInstance(conf);
434     final AdminProtos.SlowLogResponseRequest request =
435       AdminProtos.SlowLogResponseRequest.newBuilder().setLimit(500000).build();
436     final AdminProtos.SlowLogResponseRequest largeLogRequest =
437       AdminProtos.SlowLogResponseRequest.newBuilder()
438         .setLimit(500000)
439         .setLogType(AdminProtos.SlowLogResponseRequest.LogType.LARGE_LOG)
440         .build();
441     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
442     LOG.debug("Initially ringbuffer of Slow Log records is empty");
443 
444     for (int j = 0; j < 1000; j++) {
445 
446       new Thread(new Runnable() {
447         @Override public void run() {
448           for (int i = 0; i < 3500; i++) {
449             RpcLogDetails rpcLogDetails =
450               getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
451             namedQueueRecorder.addRecord(rpcLogDetails);
452           }
453         }
454       }).start();
455 
456     }
457 
458     Thread.sleep(500);
459 
460     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(
461       7000, new Waiter.Predicate<Exception>() {
462         @Override
463         public boolean evaluate() throws Exception {
464           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() > 10000;
465         }
466       }));
467     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(
468       7000, new Waiter.Predicate<Exception>() {
469         @Override
470         public boolean evaluate() throws Exception {
471           return TestNamedQueueRecorder.this.getSlowLogPayloads(largeLogRequest).size() > 10000;
472         }
473       }));
474   }
475 
476   @Test
477   public void testSlowLargeLogEvents() throws Exception {
478     Configuration conf = applySlowLogRecorderConf(28);
479     Constructor<NamedQueueRecorder> constructor =
480       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
481     constructor.setAccessible(true);
482     namedQueueRecorder = constructor.newInstance(conf);
483 
484     final AdminProtos.SlowLogResponseRequest request =
485       AdminProtos.SlowLogResponseRequest.newBuilder().setLimit(14 * 11).build();
486 
487     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
488     LOG.debug("Initially ringbuffer of Slow Log records is empty");
489 
490     boolean isSlowLog;
491     boolean isLargeLog;
492     for (int i = 0; i < 14 * 11; i++) {
493       if (i % 2 == 0) {
494         isSlowLog = true;
495         isLargeLog = false;
496       } else {
497         isSlowLog = false;
498         isLargeLog = true;
499       }
500       RpcLogDetails rpcLogDetails =
501         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1),
502           isSlowLog, isLargeLog);
503       namedQueueRecorder.addRecord(rpcLogDetails);
504     }
505     LOG.debug("Added 14 * 11 records, ringbuffer should only provide latest 14 records");
506 
507     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
508       new Waiter.Predicate<Exception>() {
509         @Override
510         public boolean evaluate() throws Exception {
511           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 14;
512         }
513       }));
514 
515     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
516       new Waiter.Predicate<Exception>() {
517         @Override
518         public boolean evaluate() throws Exception {
519           List<TooSlowLog.SlowLogPayload> slowLogPayloads =
520             TestNamedQueueRecorder.this.getSlowLogPayloads(request);
521 
522           // confirm strict order of slow log payloads
523           return slowLogPayloads.size() == 14 && TestNamedQueueRecorder.this
524             .confirmPayloadParams(0, 153, slowLogPayloads) && TestNamedQueueRecorder.this
525             .confirmPayloadParams(1, 151, slowLogPayloads) && TestNamedQueueRecorder.this
526             .confirmPayloadParams(2, 149, slowLogPayloads) && TestNamedQueueRecorder.this
527             .confirmPayloadParams(3, 147, slowLogPayloads) && TestNamedQueueRecorder.this
528             .confirmPayloadParams(4, 145, slowLogPayloads) && TestNamedQueueRecorder.this
529             .confirmPayloadParams(5, 143, slowLogPayloads) && TestNamedQueueRecorder.this
530             .confirmPayloadParams(6, 141, slowLogPayloads) && TestNamedQueueRecorder.this
531             .confirmPayloadParams(7, 139, slowLogPayloads) && TestNamedQueueRecorder.this
532             .confirmPayloadParams(8, 137, slowLogPayloads) && TestNamedQueueRecorder.this
533             .confirmPayloadParams(9, 135, slowLogPayloads) && TestNamedQueueRecorder.this
534             .confirmPayloadParams(10, 133, slowLogPayloads) && TestNamedQueueRecorder.this
535             .confirmPayloadParams(11, 131, slowLogPayloads) && TestNamedQueueRecorder.this
536             .confirmPayloadParams(12, 129, slowLogPayloads) && TestNamedQueueRecorder.this
537             .confirmPayloadParams(13, 127, slowLogPayloads);
538         }
539       })
540     );
541 
542     final AdminProtos.SlowLogResponseRequest largeLogRequest =
543       AdminProtos.SlowLogResponseRequest.newBuilder()
544         .setLimit(14 * 11)
545         .setLogType(AdminProtos.SlowLogResponseRequest.LogType.LARGE_LOG)
546         .build();
547 
548     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
549       new Waiter.Predicate<Exception>() {
550         @Override
551         public boolean evaluate() throws Exception {
552           return TestNamedQueueRecorder.this.getSlowLogPayloads(largeLogRequest).size() == 14;
553         }
554       }));
555 
556     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
557       new Waiter.Predicate<Exception>() {
558         @Override
559         public boolean evaluate() throws Exception {
560           List<TooSlowLog.SlowLogPayload> largeLogPayloads =
561             TestNamedQueueRecorder.this.getSlowLogPayloads(largeLogRequest);
562 
563           // confirm strict order of slow log payloads
564           return largeLogPayloads.size() == 14 && TestNamedQueueRecorder.this
565             .confirmPayloadParams(0, 154, largeLogPayloads) && TestNamedQueueRecorder.this
566             .confirmPayloadParams(1, 152, largeLogPayloads) && TestNamedQueueRecorder.this
567             .confirmPayloadParams(2, 150, largeLogPayloads) && TestNamedQueueRecorder.this
568             .confirmPayloadParams(3, 148, largeLogPayloads) && TestNamedQueueRecorder.this
569             .confirmPayloadParams(4, 146, largeLogPayloads) && TestNamedQueueRecorder.this
570             .confirmPayloadParams(5, 144, largeLogPayloads) && TestNamedQueueRecorder.this
571             .confirmPayloadParams(6, 142, largeLogPayloads) && TestNamedQueueRecorder.this
572             .confirmPayloadParams(7, 140, largeLogPayloads) && TestNamedQueueRecorder.this
573             .confirmPayloadParams(8, 138, largeLogPayloads) && TestNamedQueueRecorder.this
574             .confirmPayloadParams(9, 136, largeLogPayloads) && TestNamedQueueRecorder.this
575             .confirmPayloadParams(10, 134, largeLogPayloads) && TestNamedQueueRecorder.this
576             .confirmPayloadParams(11, 132, largeLogPayloads) && TestNamedQueueRecorder.this
577             .confirmPayloadParams(12, 130, largeLogPayloads) && TestNamedQueueRecorder.this
578             .confirmPayloadParams(13, 128, largeLogPayloads);
579         }
580       })
581     );
582   }
583 
584   @Test
585   public void testSlowLogMixedFilters() throws Exception {
586 
587     Configuration conf = applySlowLogRecorderConf(30);
588     Constructor<NamedQueueRecorder> constructor =
589       NamedQueueRecorder.class.getDeclaredConstructor(Configuration.class);
590     constructor.setAccessible(true);
591     namedQueueRecorder = constructor.newInstance(conf);
592     final AdminProtos.SlowLogResponseRequest request =
593       AdminProtos.SlowLogResponseRequest.newBuilder()
594         .setLimit(15)
595         .setUserName("userName_87")
596         .setClientAddress("client_88")
597         .build();
598 
599     Assert.assertEquals(getSlowLogPayloads(request).size(), 0);
600 
601     for (int i = 0; i < 100; i++) {
602       RpcLogDetails rpcLogDetails =
603         getRpcLogDetails("userName_" + (i + 1), "client_" + (i + 1), "class_" + (i + 1));
604       namedQueueRecorder.addRecord(rpcLogDetails);
605     }
606 
607     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
608       new Waiter.Predicate<Exception>() {
609         @Override
610         public boolean evaluate() throws Exception {
611           return TestNamedQueueRecorder.this.getSlowLogPayloads(request).size() == 2;
612         }
613       }));
614 
615     AdminProtos.SlowLogResponseRequest request2 = AdminProtos.SlowLogResponseRequest.newBuilder()
616       .setLimit(15)
617       .setUserName("userName_1")
618       .setClientAddress("client_2")
619       .build();
620     Assert.assertEquals(0, getSlowLogPayloads(request2).size());
621 
622     AdminProtos.SlowLogResponseRequest request3 =
623       AdminProtos.SlowLogResponseRequest.newBuilder()
624         .setLimit(15)
625         .setUserName("userName_87")
626         .setClientAddress("client_88")
627         .setFilterByOperator(AdminProtos.SlowLogResponseRequest.FilterByOperator.AND)
628         .build();
629     Assert.assertEquals(0, getSlowLogPayloads(request3).size());
630 
631     AdminProtos.SlowLogResponseRequest request4 =
632       AdminProtos.SlowLogResponseRequest.newBuilder()
633         .setLimit(15)
634         .setUserName("userName_87")
635         .setClientAddress("client_87")
636         .setFilterByOperator(AdminProtos.SlowLogResponseRequest.FilterByOperator.AND)
637         .build();
638     Assert.assertEquals(1, getSlowLogPayloads(request4).size());
639 
640     AdminProtos.SlowLogResponseRequest request5 =
641       AdminProtos.SlowLogResponseRequest.newBuilder()
642         .setLimit(15)
643         .setUserName("userName_88")
644         .setClientAddress("client_89")
645         .setFilterByOperator(AdminProtos.SlowLogResponseRequest.FilterByOperator.OR)
646         .build();
647     Assert.assertEquals(2, getSlowLogPayloads(request5).size());
648 
649     final AdminProtos.SlowLogResponseRequest requestSlowLog =
650       AdminProtos.SlowLogResponseRequest.newBuilder()
651         .setLimit(15)
652         .build();
653     Assert.assertNotEquals(-1, HBASE_TESTING_UTILITY.waitFor(3000,
654       new Waiter.Predicate<Exception>() {
655         @Override
656         public boolean evaluate() throws Exception {
657           return TestNamedQueueRecorder.this.getSlowLogPayloads(requestSlowLog).size() == 15;
658         }
659       }));
660   }
661 
662   static RpcLogDetails getRpcLogDetails(String userName, String clientAddress, String className) {
663     return new RpcLogDetails(null, getMessage(), clientAddress, 0, className, true, true, 0, 0,
664       userName);
665   }
666 
667   private RpcLogDetails getRpcLogDetails(String userName, String clientAddress,
668       String className, boolean isSlowLog, boolean isLargeLog) {
669     return new RpcLogDetails(null, getMessage(), clientAddress, 0, className,
670       isSlowLog, isLargeLog, 0, 0, userName);
671   }
672 
673   private static Message getMessage() {
674     i = (i + 1) % 3;
675     Message message = null;
676     switch (i) {
677       case 0: {
678         message = ClientProtos.ScanRequest.newBuilder()
679           .setRegion(HBaseProtos.RegionSpecifier.newBuilder()
680             .setValue(ByteString.copyFromUtf8("region1"))
681             .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME)
682             .build())
683           .build();
684         break;
685       }
686       case 1: {
687         message = ClientProtos.MutateRequest.newBuilder()
688           .setRegion(HBaseProtos.RegionSpecifier.newBuilder()
689             .setValue(ByteString.copyFromUtf8("region2"))
690             .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME))
691           .setMutation(ClientProtos.MutationProto.newBuilder()
692             .setRow(ByteString.copyFromUtf8("row123"))
693             .build())
694           .build();
695         break;
696       }
697       case 2: {
698         message = ClientProtos.GetRequest.newBuilder()
699           .setRegion(HBaseProtos.RegionSpecifier.newBuilder()
700             .setValue(ByteString.copyFromUtf8("region2"))
701             .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME))
702           .setGet(ClientProtos.Get.newBuilder()
703             .setRow(ByteString.copyFromUtf8("row123"))
704             .build())
705           .build();
706         break;
707       }
708       default:
709         throw new RuntimeException("Not supposed to get here?");
710     }
711 
712     return message;
713 
714   }
715 
716 }