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  package org.apache.hadoop.hbase.trace;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertTrue;
23  
24  import java.lang.reflect.Method;
25  import java.util.Collection;
26  
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.testclassification.MediumTests;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.Waiter;
31  import org.apache.hadoop.hbase.client.Put;
32  import org.apache.hadoop.hbase.client.Table;
33  import org.apache.htrace.Sampler;
34  import org.apache.htrace.Span;
35  import org.apache.htrace.Trace;
36  import org.apache.htrace.TraceScope;
37  import org.apache.htrace.TraceTree;
38  import org.apache.htrace.impl.POJOSpanReceiver;
39  import org.junit.AfterClass;
40  import org.junit.BeforeClass;
41  import org.junit.Test;
42  import org.junit.experimental.categories.Category;
43  
44  import com.google.common.collect.Multimap;
45  
46  @Category(MediumTests.class)
47  public class TestHTraceHooks {
48  
49    private static final byte[] FAMILY_BYTES = "family".getBytes();
50    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
51    private static POJOSpanReceiver rcvr;
52    private static long ROOT_SPAN_ID = 0;
53  
54    @BeforeClass
55    public static void before() throws Exception {
56  
57      // Find out what the right value to use fo SPAN_ROOT_ID after HTRACE-111. We use HTRACE-32
58      // to find out to detect if we are using HTrace 3.2 or not.
59      try {
60          Method m = Span.class.getMethod("addKVAnnotation", String.class, String.class);
61      } catch (NoSuchMethodException e) {
62        ROOT_SPAN_ID = 0x74aceL; // Span.SPAN_ROOT_ID pre HTrace-3.2
63      }
64  
65      TEST_UTIL.startMiniCluster(2, 3);
66      rcvr = new POJOSpanReceiver(new HBaseHTraceConfiguration(TEST_UTIL.getConfiguration()));
67      Trace.addReceiver(rcvr);
68    }
69  
70    @AfterClass
71    public static void after() throws Exception {
72      TEST_UTIL.shutdownMiniCluster();
73      Trace.removeReceiver(rcvr);
74      rcvr = null;
75    }
76  
77    @Test
78    public void testTraceCreateTable() throws Exception {
79      TraceScope tableCreationSpan = Trace.startSpan("creating table", Sampler.ALWAYS);
80      Table table;
81      try {
82  
83        table = TEST_UTIL.createTable(TableName.valueOf("table"),
84          FAMILY_BYTES);
85      } finally {
86        tableCreationSpan.close();
87      }
88  
89      // Some table creation is async.  Need to make sure that everything is full in before
90      // checking to see if the spans are there.
91      TEST_UTIL.waitFor(1000, new Waiter.Predicate<Exception>() {
92        @Override
93        public boolean evaluate() throws Exception {
94          return rcvr.getSpans().size() >= 5;
95        }
96      });
97  
98      Collection<Span> spans = rcvr.getSpans();
99      TraceTree traceTree = new TraceTree(spans);
100     Collection<Span> roots = traceTree.getSpansByParent().find(ROOT_SPAN_ID);
101 
102     assertEquals(1, roots.size());
103     Span createTableRoot = roots.iterator().next();
104 
105     assertEquals("creating table", createTableRoot.getDescription());
106 
107     int createTableCount = 0;
108 
109     for (Span s : traceTree.getSpansByParent().find(createTableRoot.getSpanId())) {
110       if (s.getDescription().startsWith("MasterService.CreateTable")) {
111         createTableCount++;
112       }
113     }
114 
115     assertTrue(createTableCount >= 1);
116     assertTrue(traceTree.getSpansByParent().find(createTableRoot.getSpanId()).size() > 3);
117     assertTrue(spans.size() > 5);
118 
119     Put put = new Put("row".getBytes());
120     put.add(FAMILY_BYTES, "col".getBytes(), "value".getBytes());
121 
122     TraceScope putSpan = Trace.startSpan("doing put", Sampler.ALWAYS);
123     try {
124       table.put(put);
125     } finally {
126       putSpan.close();
127     }
128 
129     spans = rcvr.getSpans();
130     traceTree = new TraceTree(spans);
131     roots = traceTree.getSpansByParent().find(ROOT_SPAN_ID);
132 
133     assertEquals(2, roots.size());
134     Span putRoot = null;
135     for (Span root : roots) {
136       if (root.getDescription().equals("doing put")) {
137         putRoot = root;
138       }
139     }
140 
141     assertNotNull(putRoot);
142   }
143 }