View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.regionserver.wal;
20  
21  import org.apache.hadoop.fs.Path;
22  import org.apache.hadoop.hbase.testclassification.SmallTests;
23  import java.util.concurrent.CountDownLatch;
24  import java.util.concurrent.TimeUnit;
25  import org.apache.hadoop.hbase.TableName;
26  import org.apache.hadoop.hbase.wal.WALKey;
27  import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
28  import org.junit.Rule;
29  import org.junit.Test;
30  import org.junit.experimental.categories.Category;
31  import org.junit.rules.TestName;
32  
33  import static org.junit.Assert.assertEquals;
34  import static org.mockito.Mockito.mock;
35  import static org.mockito.Mockito.times;
36  import static org.mockito.Mockito.verify;
37  
38  @Category(SmallTests.class)
39  public class TestMetricsWAL {
40    @Rule
41    public TestName name = new TestName();
42  
43    @Test
44    public void testLogRollRequested() throws Exception {
45      MetricsWALSource source = mock(MetricsWALSourceImpl.class);
46      MetricsWAL metricsWAL = new MetricsWAL(source);
47      metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.ERROR);
48      metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.LOW_REPLICATION);
49      metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.SLOW_SYNC);
50      metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.SIZE);
51  
52      // Log roll was requested four times
53      verify(source, times(4)).incrementLogRollRequested();
54      // One was because of an IO error.
55      verify(source, times(1)).incrementErrorLogRoll();
56      // One was because of low replication on the hlog.
57      verify(source, times(1)).incrementLowReplicationLogRoll();
58      // One was because of slow sync on the hlog.
59      verify(source, times(1)).incrementSlowSyncLogRoll();
60      // One was because of hlog file length limit.
61      verify(source, times(1)).incrementSizeLogRoll();
62    }
63  
64    @Test
65    public void testPostSync() throws Exception {
66      long nanos = TimeUnit.MILLISECONDS.toNanos(145);
67      MetricsWALSource source = mock(MetricsWALSourceImpl.class);
68      MetricsWAL metricsWAL = new MetricsWAL(source);
69      metricsWAL.postSync(nanos, 1);
70      verify(source, times(1)).incrementSyncTime(145);
71    }
72  
73    @Test
74    public void testWalWrittenInBytes() throws Exception {
75      MetricsWALSource source = mock(MetricsWALSourceImpl.class);
76      MetricsWAL metricsWAL = new MetricsWAL(source);
77      TableName tableName = TableName.valueOf("foo");
78      WALKey walKey = new WALKey(null, tableName, -1);
79      metricsWAL.postAppend(100, 900, walKey, null);
80      metricsWAL.postAppend(200, 2000, walKey, null);
81      verify(source, times(1)).incrementWrittenBytes(100);
82      verify(source, times(1)).incrementWrittenBytes(200);
83    }
84  
85    @Test
86    public void testPerTableWALMetrics() throws Exception {
87      final MetricsWALSourceImpl source = new MetricsWALSourceImpl("foo", "foo", "foo", "foo");
88      final int numThreads = 10;
89      final int numIters = 10;
90      final CountDownLatch latch = new CountDownLatch(numThreads);
91      for (int i = 0; i < numThreads; i++) {
92        final TableName tableName = TableName.valueOf("tab_" + i);
93        final long size = i;
94        new Thread(new Runnable() {
95          @Override
96          public void run() {
97            for (int j = 0; j < numIters; j++) {
98              source.incrementAppendCount(tableName);
99              source.incrementAppendSize(tableName, size);
100           }
101           latch.countDown();
102         }
103       }).start();
104     }
105     // Wait for threads to finish.
106     latch.await();
107     DynamicMetricsRegistry registry = source.getMetricsRegistry();
108     // Validate the metrics
109     for (int i = 0; i < numThreads; i++) {
110       TableName tableName = TableName.valueOf("tab_" + i);
111       long tableAppendCount =
112           registry.getCounter(tableName + "." + MetricsWALSource.APPEND_COUNT, -1).value();
113       assertEquals(numIters, tableAppendCount);
114       long tableAppendSize =
115           registry.getCounter(tableName + "." + MetricsWALSource.APPEND_SIZE, -1).value();
116       assertEquals(i * numIters, tableAppendSize);
117     }
118   }
119 
120   @Test
121   public void testLogRolls() {
122     String testName = name.getMethodName();
123     MetricsWALSource source = new MetricsWALSourceImpl(testName, testName, testName, testName);
124     MetricsWAL metricsWAL = new MetricsWAL(source);
125     Path path1 = new Path("path-1");
126     int count = 1;
127     // oldPath is null but newPath is not null;
128     metricsWAL.postLogRoll(null, path1);
129     assertEquals(count, source.getSuccessfulLogRolls());
130 
131     // Simulating a case where AbstractFSWAL#replaceWriter fails
132     metricsWAL.postLogRoll(path1, path1);
133     assertEquals(count, source.getSuccessfulLogRolls());
134 
135     count++;
136     Path path2 = new Path("path-2");
137     metricsWAL.postLogRoll(path1, path2);
138     assertEquals(count, source.getSuccessfulLogRolls());
139   }
140 }