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.client; 019 020import static org.apache.hadoop.hbase.client.trace.hamcrest.AttributesMatchers.containsEntry; 021import static org.apache.hadoop.hbase.client.trace.hamcrest.AttributesMatchers.containsEntryWithStringValuesOf; 022import static org.apache.hadoop.hbase.client.trace.hamcrest.SpanDataMatchers.hasAttributes; 023import static org.apache.hadoop.hbase.client.trace.hamcrest.SpanDataMatchers.hasEnded; 024import static org.apache.hadoop.hbase.client.trace.hamcrest.SpanDataMatchers.hasKind; 025import static org.apache.hadoop.hbase.client.trace.hamcrest.SpanDataMatchers.hasName; 026import static org.apache.hadoop.hbase.client.trace.hamcrest.SpanDataMatchers.hasStatusWithCode; 027import static org.apache.hadoop.hbase.client.trace.hamcrest.TraceTestUtil.buildConnectionAttributesMatcher; 028import static org.apache.hadoop.hbase.client.trace.hamcrest.TraceTestUtil.buildTableAttributesMatcher; 029import static org.hamcrest.MatcherAssert.assertThat; 030import static org.hamcrest.Matchers.allOf; 031import static org.hamcrest.Matchers.containsInAnyOrder; 032import static org.hamcrest.Matchers.hasItem; 033 034import io.opentelemetry.api.trace.SpanKind; 035import io.opentelemetry.api.trace.StatusCode; 036import io.opentelemetry.sdk.testing.junit4.OpenTelemetryRule; 037import io.opentelemetry.sdk.trace.data.SpanData; 038import java.io.IOException; 039import java.util.Arrays; 040import java.util.concurrent.CompletableFuture; 041import java.util.concurrent.TimeUnit; 042import org.apache.hadoop.conf.Configuration; 043import org.apache.hadoop.hbase.HBaseClassTestRule; 044import org.apache.hadoop.hbase.HBaseConfiguration; 045import org.apache.hadoop.hbase.HConstants; 046import org.apache.hadoop.hbase.HRegionLocation; 047import org.apache.hadoop.hbase.MatcherPredicate; 048import org.apache.hadoop.hbase.RegionLocations; 049import org.apache.hadoop.hbase.ServerName; 050import org.apache.hadoop.hbase.TableName; 051import org.apache.hadoop.hbase.Waiter; 052import org.apache.hadoop.hbase.security.User; 053import org.apache.hadoop.hbase.security.UserProvider; 054import org.apache.hadoop.hbase.testclassification.ClientTests; 055import org.apache.hadoop.hbase.testclassification.MediumTests; 056import org.hamcrest.Matcher; 057import org.junit.After; 058import org.junit.Before; 059import org.junit.ClassRule; 060import org.junit.Rule; 061import org.junit.Test; 062import org.junit.experimental.categories.Category; 063import org.slf4j.Logger; 064import org.slf4j.LoggerFactory; 065 066import org.apache.hbase.thirdparty.com.google.common.io.Closeables; 067 068@Category({ ClientTests.class, MediumTests.class }) 069public class TestAsyncRegionLocatorTracing { 070 private static final Logger LOG = LoggerFactory.getLogger(TestAsyncRegionLocatorTracing.class); 071 072 @ClassRule 073 public static final HBaseClassTestRule CLASS_RULE = 074 HBaseClassTestRule.forClass(TestAsyncRegionLocatorTracing.class); 075 076 private static final Configuration CONF = HBaseConfiguration.create(); 077 078 private AsyncConnectionImpl conn; 079 080 private RegionLocations locs; 081 082 @Rule 083 public OpenTelemetryRule traceRule = OpenTelemetryRule.create(); 084 085 @Before 086 public void setUp() throws IOException { 087 RegionInfo metaRegionInfo = RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).build(); 088 locs = new RegionLocations( 089 new HRegionLocation(metaRegionInfo, 090 ServerName.valueOf("127.0.0.1", 12345, System.currentTimeMillis())), 091 new HRegionLocation(RegionReplicaUtil.getRegionInfoForReplica(metaRegionInfo, 1), 092 ServerName.valueOf("127.0.0.2", 12345, System.currentTimeMillis())), 093 new HRegionLocation(RegionReplicaUtil.getRegionInfoForReplica(metaRegionInfo, 2), 094 ServerName.valueOf("127.0.0.3", 12345, System.currentTimeMillis()))); 095 User user = UserProvider.instantiate(CONF).getCurrent(); 096 conn = new AsyncConnectionImpl(CONF, new DoNothingConnectionRegistry(CONF, user) { 097 098 @Override 099 public CompletableFuture<RegionLocations> getMetaRegionLocations() { 100 return CompletableFuture.completedFuture(locs); 101 } 102 }, "test", user); 103 } 104 105 @After 106 public void tearDown() throws IOException { 107 Closeables.close(conn, true); 108 } 109 110 private SpanData waitSpan(String name) { 111 return waitSpan(hasName(name)); 112 } 113 114 private SpanData waitSpan(Matcher<SpanData> matcher) { 115 Matcher<SpanData> spanLocator = allOf(matcher, hasEnded()); 116 try { 117 Waiter.waitFor(CONF, 1000, new MatcherPredicate<>("waiting for span", 118 () -> traceRule.getSpans(), hasItem(spanLocator))); 119 } catch (AssertionError e) { 120 LOG.error("AssertionError while waiting for matching span. Span reservoir contains: {}", 121 traceRule.getSpans()); 122 throw e; 123 } 124 return traceRule.getSpans().stream().filter(spanLocator::matches).findFirst() 125 .orElseThrow(AssertionError::new); 126 } 127 128 @Test 129 public void testClearCache() { 130 conn.getLocator().clearCache(); 131 SpanData span = waitSpan("AsyncRegionLocator.clearCache"); 132 assertThat(span, allOf(hasStatusWithCode(StatusCode.OK), hasKind(SpanKind.INTERNAL), 133 buildConnectionAttributesMatcher(conn))); 134 } 135 136 @Test 137 public void testClearCacheServerName() { 138 ServerName sn = ServerName.valueOf("127.0.0.1", 12345, System.currentTimeMillis()); 139 conn.getLocator().clearCache(sn); 140 SpanData span = waitSpan("AsyncRegionLocator.clearCache"); 141 assertThat(span, 142 allOf(hasStatusWithCode(StatusCode.OK), hasKind(SpanKind.INTERNAL), 143 buildConnectionAttributesMatcher(conn), 144 hasAttributes(containsEntry("db.hbase.server.name", sn.getServerName())))); 145 } 146 147 @Test 148 public void testClearCacheTableName() { 149 conn.getLocator().clearCache(TableName.META_TABLE_NAME); 150 SpanData span = waitSpan("AsyncRegionLocator.clearCache"); 151 assertThat(span, 152 allOf(hasStatusWithCode(StatusCode.OK), hasKind(SpanKind.INTERNAL), 153 buildConnectionAttributesMatcher(conn), 154 buildTableAttributesMatcher(TableName.META_TABLE_NAME))); 155 } 156 157 @Test 158 public void testGetRegionLocation() { 159 conn.getLocator().getRegionLocation(TableName.META_TABLE_NAME, HConstants.EMPTY_START_ROW, 160 RegionLocateType.CURRENT, TimeUnit.SECONDS.toNanos(1)).join(); 161 SpanData span = waitSpan("AsyncRegionLocator.getRegionLocation"); 162 assertThat(span, 163 allOf(hasStatusWithCode(StatusCode.OK), hasKind(SpanKind.INTERNAL), 164 buildConnectionAttributesMatcher(conn), 165 buildTableAttributesMatcher(TableName.META_TABLE_NAME), 166 hasAttributes(containsEntryWithStringValuesOf("db.hbase.regions", 167 locs.getDefaultRegionLocation().getRegion().getRegionNameAsString())))); 168 } 169 170 @Test 171 public void testGetRegionLocations() { 172 conn.getLocator().getRegionLocations(TableName.META_TABLE_NAME, HConstants.EMPTY_START_ROW, 173 RegionLocateType.CURRENT, false, TimeUnit.SECONDS.toNanos(1)).join(); 174 SpanData span = waitSpan("AsyncRegionLocator.getRegionLocations"); 175 String[] expectedRegions = 176 Arrays.stream(locs.getRegionLocations()).map(HRegionLocation::getRegion) 177 .map(RegionInfo::getRegionNameAsString).toArray(String[]::new); 178 assertThat(span, allOf(hasStatusWithCode(StatusCode.OK), hasKind(SpanKind.INTERNAL), 179 buildConnectionAttributesMatcher(conn), 180 buildTableAttributesMatcher(TableName.META_TABLE_NAME), hasAttributes( 181 containsEntryWithStringValuesOf("db.hbase.regions", containsInAnyOrder(expectedRegions))))); 182 } 183}