001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver.wal; 019 020import static org.junit.Assert.assertEquals; 021import static org.mockito.Mockito.mock; 022import static org.mockito.Mockito.times; 023import static org.mockito.Mockito.verify; 024 025import java.util.concurrent.CountDownLatch; 026import java.util.concurrent.TimeUnit; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.testclassification.MiscTests; 030import org.apache.hadoop.hbase.testclassification.SmallTests; 031import org.apache.hadoop.hbase.wal.WALKey; 032import org.apache.hadoop.hbase.wal.WALKeyImpl; 033import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry; 034import org.junit.ClassRule; 035import org.junit.Test; 036import org.junit.experimental.categories.Category; 037 038@Category({MiscTests.class, SmallTests.class}) 039public class TestMetricsWAL { 040 041 @ClassRule 042 public static final HBaseClassTestRule CLASS_RULE = 043 HBaseClassTestRule.forClass(TestMetricsWAL.class); 044 045 @Test 046 public void testLogRollRequested() throws Exception { 047 MetricsWALSource source = mock(MetricsWALSourceImpl.class); 048 MetricsWAL metricsWAL = new MetricsWAL(source); 049 metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.ERROR); 050 metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.LOW_REPLICATION); 051 metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.SLOW_SYNC); 052 metricsWAL.logRollRequested(WALActionsListener.RollRequestReason.SIZE); 053 054 // Log roll was requested four times 055 verify(source, times(4)).incrementLogRollRequested(); 056 // One was because of an IO error. 057 verify(source, times(1)).incrementErrorLogRoll(); 058 // One was because of low replication on the hlog. 059 verify(source, times(1)).incrementLowReplicationLogRoll(); 060 // One was because of slow sync on the hlog. 061 verify(source, times(1)).incrementSlowSyncLogRoll(); 062 // One was because of hlog file length limit. 063 verify(source, times(1)).incrementSizeLogRoll(); 064 } 065 066 @Test 067 public void testPostSync() throws Exception { 068 long nanos = TimeUnit.MILLISECONDS.toNanos(145); 069 MetricsWALSource source = mock(MetricsWALSourceImpl.class); 070 MetricsWAL metricsWAL = new MetricsWAL(source); 071 metricsWAL.postSync(nanos, 1); 072 verify(source, times(1)).incrementSyncTime(145); 073 } 074 075 @Test 076 public void testSlowAppend() throws Exception { 077 MetricsWALSource source = new MetricsWALSourceImpl(); 078 MetricsWAL metricsWAL = new MetricsWAL(source); 079 TableName tableName = TableName.valueOf("foo"); 080 WALKey walKey = new WALKeyImpl(null, tableName, -1); 081 // One not so slow append (< 1000) 082 metricsWAL.postAppend(1, 900, walKey, null); 083 // Two slow appends (> 1000) 084 metricsWAL.postAppend(1, 1010, walKey, null); 085 metricsWAL.postAppend(1, 2000, walKey, null); 086 assertEquals(2, source.getSlowAppendCount()); 087 } 088 089 @Test 090 public void testWalWrittenInBytes() throws Exception { 091 MetricsWALSource source = mock(MetricsWALSourceImpl.class); 092 MetricsWAL metricsWAL = new MetricsWAL(source); 093 TableName tableName = TableName.valueOf("foo"); 094 WALKey walKey = new WALKeyImpl(null, tableName, -1); 095 metricsWAL.postAppend(100, 900, walKey, null); 096 metricsWAL.postAppend(200, 2000, walKey, null); 097 verify(source, times(1)).incrementWrittenBytes(100); 098 verify(source, times(1)).incrementWrittenBytes(200); 099 } 100 101 @Test 102 public void testPerTableWALMetrics() throws Exception { 103 MetricsWALSourceImpl source = new MetricsWALSourceImpl("foo", "foo", "foo", "foo"); 104 final int numThreads = 10; 105 final int numIters = 10; 106 CountDownLatch latch = new CountDownLatch(numThreads); 107 for (int i = 0; i < numThreads; i++) { 108 final TableName tableName = TableName.valueOf("tab_" + i); 109 long size = i; 110 new Thread(() -> { 111 for (int j = 0; j < numIters; j++) { 112 source.incrementAppendCount(tableName); 113 source.incrementAppendSize(tableName, size); 114 } 115 latch.countDown(); 116 }).start(); 117 } 118 // Wait for threads to finish. 119 latch.await(); 120 DynamicMetricsRegistry registry = source.getMetricsRegistry(); 121 // Validate the metrics 122 for (int i = 0; i < numThreads; i++) { 123 TableName tableName = TableName.valueOf("tab_" + i); 124 long tableAppendCount = 125 registry.getCounter(tableName + "." + MetricsWALSource.APPEND_COUNT, -1).value(); 126 assertEquals(numIters, tableAppendCount); 127 long tableAppendSize = 128 registry.getCounter(tableName + "." + MetricsWALSource.APPEND_SIZE, -1).value(); 129 assertEquals(i * numIters, tableAppendSize); 130 } 131 } 132}