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