You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@htrace.apache.org by cm...@apache.org on 2014/12/06 05:07:37 UTC

[1/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Repository: incubator-htrace
Updated Branches:
  refs/heads/master c4a0d5d4a -> a27cd4dab


http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/src/test/java/org/apache/htrace/TestHTraceSpanToZipkinSpan.java
----------------------------------------------------------------------
diff --git a/htrace-zipkin/src/test/java/org/apache/htrace/TestHTraceSpanToZipkinSpan.java b/htrace-zipkin/src/test/java/org/apache/htrace/TestHTraceSpanToZipkinSpan.java
new file mode 100644
index 0000000..b6b4c43
--- /dev/null
+++ b/htrace-zipkin/src/test/java/org/apache/htrace/TestHTraceSpanToZipkinSpan.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace;
+
+import com.twitter.zipkin.gen.zipkinCoreConstants;
+
+import org.apache.htrace.Span;
+import org.apache.htrace.Trace;
+import org.apache.htrace.impl.MilliSpan;
+import org.apache.htrace.impl.POJOSpanReceiver;
+import org.apache.htrace.zipkin.HTraceToZipkinConverter;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Creates HTrace and then convert it to Zipkin trace and checks whether it is a valid span or not.
+ */
+public class TestHTraceSpanToZipkinSpan {
+
+  private static final String ROOT_SPAN_DESC = "ROOT";
+
+  @Test
+  public void testHTraceToZipkin() throws IOException {
+    POJOSpanReceiver psr = new POJOSpanReceiver();
+    Trace.addReceiver(psr);
+
+    Span rootSpan = new MilliSpan(ROOT_SPAN_DESC, 1, Span.ROOT_SPAN_ID, 100, "test");
+    Span innerOne = rootSpan.child("Some good work");
+    Span innerTwo = innerOne.child("Some more good work");
+    innerTwo.stop();
+    innerOne.stop();
+    rootSpan.addKVAnnotation("foo".getBytes(), "bar".getBytes());
+    rootSpan.addTimelineAnnotation("timeline");
+    rootSpan.stop();
+
+    for (Span s : new Span[] {rootSpan, innerOne, innerTwo}) {
+      com.twitter.zipkin.gen.Span zs =
+          new HTraceToZipkinConverter(12345, (short) 12).convert(s);
+      assertSpansAreEquivalent(s, zs);
+    }
+  }
+
+  @Test
+  public void testHTraceAnnotationTimestamp() throws IOException, InterruptedException {
+
+    String traceName = "testHTraceAnnotationTimestamp";
+    long startTime = System.currentTimeMillis() * 1000;
+    Span ms = new MilliSpan(traceName, 1, Span.ROOT_SPAN_ID, 2, traceName);
+
+    Thread.sleep(500);
+    long annoStartTime = System.currentTimeMillis() * 1000;
+    Thread.sleep(500);
+    ms.addTimelineAnnotation("anno");
+    Thread.sleep(500);
+    long annoEndTime = System.currentTimeMillis() * 1000;
+    Thread.sleep(500);
+    ms.stop();
+    long endTime = System.currentTimeMillis() * 1000;
+
+
+
+    com.twitter.zipkin.gen.Span zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms);
+
+    // Check to make sure that all times are in the proper order.
+    for (com.twitter.zipkin.gen.Annotation annotation : zs.getAnnotations()) {
+      // CS and SR should be before the annotation
+      // the annotation should be in between annotationStart and annotationEnd times
+      // SS and CR should be after annotationEnd and before endtime.
+      if (annotation.getValue().equals(zipkinCoreConstants.CLIENT_SEND)
+          || annotation.getValue().equals(zipkinCoreConstants.SERVER_RECV)) {
+        assertTrue(startTime <= annotation.getTimestamp());
+        assertTrue(annotation.getTimestamp() <= annoStartTime);
+      } else if (annotation.getValue().equals(zipkinCoreConstants.CLIENT_RECV)
+          || annotation.getValue().equals(zipkinCoreConstants.SERVER_SEND)) {
+        assertTrue(annoEndTime <= annotation.getTimestamp());
+        assertTrue(annotation.getTimestamp() <= endTime);
+      } else {
+        assertTrue(annoStartTime <= annotation.getTimestamp());
+        assertTrue(annotation.getTimestamp() <= annoEndTime);
+        assertTrue(annotation.getTimestamp() <= endTime);
+      }
+    }
+  }
+
+  @Test
+  public void testHTraceDefaultPort() throws IOException {
+    MilliSpan ms = new MilliSpan("test", 1, 2, 3, "hmaster");
+    com.twitter.zipkin.gen.Span zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms);
+    for (com.twitter.zipkin.gen.Annotation annotation:zs.getAnnotations()) {
+      assertEquals((short)60000, annotation.getHost().getPort());
+    }
+
+    ms = new MilliSpan("test", 1, 2, 3, "HregIonServer");   // make sure it's all lower cased
+    zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms);
+    for (com.twitter.zipkin.gen.Annotation annotation:zs.getAnnotations()) {
+      assertEquals((short)60020, annotation.getHost().getPort());
+    }
+  }
+
+  private void assertSpansAreEquivalent(Span s, com.twitter.zipkin.gen.Span zs) {
+    assertEquals(s.getTraceId(), zs.getTrace_id());
+    if (s.getParentId() != Span.ROOT_SPAN_ID) {
+      assertEquals(s.getParentId(), zs.getParent_id());
+    }
+    assertEquals(s.getSpanId(), zs.getId());
+    Assert.assertNotNull(zs.getAnnotations());
+    if (ROOT_SPAN_DESC.equals(zs.getName())) {
+      assertEquals(5, zs.getAnnotations().size());// two start, two stop + one timeline annotation
+      assertEquals(1, zs.getBinary_annotations().size());
+    } else {
+      assertEquals(4, zs.getAnnotations().size());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/src/test/java/org/htrace/TestHTraceSpanToZipkinSpan.java
----------------------------------------------------------------------
diff --git a/htrace-zipkin/src/test/java/org/htrace/TestHTraceSpanToZipkinSpan.java b/htrace-zipkin/src/test/java/org/htrace/TestHTraceSpanToZipkinSpan.java
deleted file mode 100644
index 80cc2bc..0000000
--- a/htrace-zipkin/src/test/java/org/htrace/TestHTraceSpanToZipkinSpan.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace;
-
-import com.twitter.zipkin.gen.zipkinCoreConstants;
-import org.htrace.impl.MilliSpan;
-import org.htrace.zipkin.HTraceToZipkinConverter;
-import org.htrace.impl.POJOSpanReceiver;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Collection;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Creates HTrace and then convert it to Zipkin trace and checks whether it is a valid span or not.
- */
-public class TestHTraceSpanToZipkinSpan {
-
-  private static final String ROOT_SPAN_DESC = "ROOT";
-
-  @Test
-  public void testHTraceToZipkin() throws IOException {
-    POJOSpanReceiver psr = new POJOSpanReceiver();
-    Trace.addReceiver(psr);
-
-    Span rootSpan = new MilliSpan(ROOT_SPAN_DESC, 1, Span.ROOT_SPAN_ID, 100, "test");
-    Span innerOne = rootSpan.child("Some good work");
-    Span innerTwo = innerOne.child("Some more good work");
-    innerTwo.stop();
-    innerOne.stop();
-    rootSpan.addKVAnnotation("foo".getBytes(), "bar".getBytes());
-    rootSpan.addTimelineAnnotation("timeline");
-    rootSpan.stop();
-
-    for (Span s : new Span[] {rootSpan, innerOne, innerTwo}) {
-      com.twitter.zipkin.gen.Span zs =
-          new HTraceToZipkinConverter(12345, (short) 12).convert(s);
-      assertSpansAreEquivalent(s, zs);
-    }
-  }
-
-  @Test
-  public void testHTraceAnnotationTimestamp() throws IOException, InterruptedException {
-
-    String traceName = "testHTraceAnnotationTimestamp";
-    long startTime = System.currentTimeMillis() * 1000;
-    Span ms = new MilliSpan(traceName, 1, Span.ROOT_SPAN_ID, 2, traceName);
-
-    Thread.sleep(500);
-    long annoStartTime = System.currentTimeMillis() * 1000;
-    Thread.sleep(500);
-    ms.addTimelineAnnotation("anno");
-    Thread.sleep(500);
-    long annoEndTime = System.currentTimeMillis() * 1000;
-    Thread.sleep(500);
-    ms.stop();
-    long endTime = System.currentTimeMillis() * 1000;
-
-
-
-    com.twitter.zipkin.gen.Span zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms);
-
-    // Check to make sure that all times are in the proper order.
-    for (com.twitter.zipkin.gen.Annotation annotation : zs.getAnnotations()) {
-      // CS and SR should be before the annotation
-      // the annotation should be in between annotationStart and annotationEnd times
-      // SS and CR should be after annotationEnd and before endtime.
-      if (annotation.getValue().equals(zipkinCoreConstants.CLIENT_SEND)
-          || annotation.getValue().equals(zipkinCoreConstants.SERVER_RECV)) {
-        assertTrue(startTime <= annotation.getTimestamp());
-        assertTrue(annotation.getTimestamp() <= annoStartTime);
-      } else if (annotation.getValue().equals(zipkinCoreConstants.CLIENT_RECV)
-          || annotation.getValue().equals(zipkinCoreConstants.SERVER_SEND)) {
-        assertTrue(annoEndTime <= annotation.getTimestamp());
-        assertTrue(annotation.getTimestamp() <= endTime);
-      } else {
-        assertTrue(annoStartTime <= annotation.getTimestamp());
-        assertTrue(annotation.getTimestamp() <= annoEndTime);
-        assertTrue(annotation.getTimestamp() <= endTime);
-      }
-    }
-  }
-
-  @Test
-  public void testHTraceDefaultPort() throws IOException {
-    MilliSpan ms = new MilliSpan("test", 1, 2, 3, "hmaster");
-    com.twitter.zipkin.gen.Span zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms);
-    for (com.twitter.zipkin.gen.Annotation annotation:zs.getAnnotations()) {
-      assertEquals((short)60000, annotation.getHost().getPort());
-    }
-
-    ms = new MilliSpan("test", 1, 2, 3, "HregIonServer");   // make sure it's all lower cased
-    zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms);
-    for (com.twitter.zipkin.gen.Annotation annotation:zs.getAnnotations()) {
-      assertEquals((short)60020, annotation.getHost().getPort());
-    }
-  }
-
-  private void assertSpansAreEquivalent(Span s, com.twitter.zipkin.gen.Span zs) {
-    assertEquals(s.getTraceId(), zs.getTrace_id());
-    if (s.getParentId() != Span.ROOT_SPAN_ID) {
-      assertEquals(s.getParentId(), zs.getParent_id());
-    }
-    assertEquals(s.getSpanId(), zs.getId());
-    Assert.assertNotNull(zs.getAnnotations());
-    if (ROOT_SPAN_DESC.equals(zs.getName())) {
-      assertEquals(5, zs.getAnnotations().size());// two start, two stop + one timeline annotation
-      assertEquals(1, zs.getBinary_annotations().size());
-    } else {
-      assertEquals(4, zs.getAnnotations().size());
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 18ca742..b404460 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@ language governing permissions and limitations under the License. -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
-  <groupId>org.htrace</groupId>
+  <groupId>org.apache.htrace</groupId>
   <artifactId>htrace</artifactId>
   <version>3.0.4</version>
   <packaging>pom</packaging>


[8/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)


Project: http://git-wip-us.apache.org/repos/asf/incubator-htrace/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-htrace/commit/a27cd4da
Tree: http://git-wip-us.apache.org/repos/asf/incubator-htrace/tree/a27cd4da
Diff: http://git-wip-us.apache.org/repos/asf/incubator-htrace/diff/a27cd4da

Branch: refs/heads/master
Commit: a27cd4dabd9a018e23f2fb14d8d916979040dc18
Parents: c4a0d5d
Author: Colin P. Mccabe <cm...@apache.org>
Authored: Fri Dec 5 20:01:21 2014 -0800
Committer: Colin P. Mccabe <cm...@apache.org>
Committed: Fri Dec 5 20:01:21 2014 -0800

----------------------------------------------------------------------
 README.md                                       |    7 +-
 htrace-core/pom.xml                             |    2 +-
 .../org/apache/htrace/HTraceConfiguration.java  |   84 +
 .../main/java/org/apache/htrace/NullScope.java  |   34 +
 .../main/java/org/apache/htrace/Sampler.java    |   54 +
 .../src/main/java/org/apache/htrace/Span.java   |  116 +
 .../java/org/apache/htrace/SpanReceiver.java    |   42 +
 .../org/apache/htrace/TimelineAnnotation.java   |   40 +
 .../src/main/java/org/apache/htrace/Trace.java  |  208 ++
 .../main/java/org/apache/htrace/TraceInfo.java  |   38 +
 .../main/java/org/apache/htrace/TraceScope.java |   82 +
 .../main/java/org/apache/htrace/TraceTree.java  |   95 +
 .../src/main/java/org/apache/htrace/Tracer.java |  125 +
 .../org/apache/htrace/impl/AlwaysSampler.java   |   32 +
 .../org/apache/htrace/impl/CountSampler.java    |   41 +
 .../htrace/impl/LocalFileSpanReceiver.java      |  137 ++
 .../java/org/apache/htrace/impl/MilliSpan.java  |  161 ++
 .../org/apache/htrace/impl/NeverSampler.java    |   33 +
 .../apache/htrace/impl/POJOSpanReceiver.java    |   58 +
 .../apache/htrace/impl/ProbabilitySampler.java  |   36 +
 .../htrace/impl/StandardOutSpanReceiver.java    |   42 +
 .../htrace/impl/TrueIfTracingSampler.java       |   37 +
 .../apache/htrace/wrappers/TraceCallable.java   |   69 +
 .../htrace/wrappers/TraceExecutorService.java   |  118 +
 .../org/apache/htrace/wrappers/TraceProxy.java  |   70 +
 .../apache/htrace/wrappers/TraceRunnable.java   |   64 +
 .../java/org/htrace/HTraceConfiguration.java    |   84 -
 .../src/main/java/org/htrace/NullScope.java     |   34 -
 .../src/main/java/org/htrace/Sampler.java       |   54 -
 htrace-core/src/main/java/org/htrace/Span.java  |  116 -
 .../src/main/java/org/htrace/SpanReceiver.java  |   42 -
 .../java/org/htrace/TimelineAnnotation.java     |   40 -
 htrace-core/src/main/java/org/htrace/Trace.java |  208 --
 .../src/main/java/org/htrace/TraceInfo.java     |   38 -
 .../src/main/java/org/htrace/TraceScope.java    |   82 -
 .../src/main/java/org/htrace/TraceTree.java     |   95 -
 .../src/main/java/org/htrace/Tracer.java        |  125 -
 .../java/org/htrace/impl/AlwaysSampler.java     |   32 -
 .../main/java/org/htrace/impl/CountSampler.java |   41 -
 .../org/htrace/impl/LocalFileSpanReceiver.java  |  137 --
 .../main/java/org/htrace/impl/MilliSpan.java    |  161 --
 .../main/java/org/htrace/impl/NeverSampler.java |   33 -
 .../java/org/htrace/impl/POJOSpanReceiver.java  |   58 -
 .../org/htrace/impl/ProbabilitySampler.java     |   36 -
 .../htrace/impl/StandardOutSpanReceiver.java    |   42 -
 .../org/htrace/impl/TrueIfTracingSampler.java   |   37 -
 .../java/org/htrace/wrappers/TraceCallable.java |   69 -
 .../htrace/wrappers/TraceExecutorService.java   |  118 -
 .../java/org/htrace/wrappers/TraceProxy.java    |   70 -
 .../java/org/htrace/wrappers/TraceRunnable.java |   64 -
 .../org/apache/htrace/TestCountSampler.java     |   40 +
 .../test/java/org/apache/htrace/TestHTrace.java |  118 +
 .../apache/htrace/TestHTraceConfiguration.java  |   63 +
 .../java/org/apache/htrace/TestSampler.java     |   53 +
 .../java/org/apache/htrace/TraceCreator.java    |  163 ++
 .../test/java/org/htrace/TestCountSampler.java  |   40 -
 .../src/test/java/org/htrace/TestHTrace.java    |  113 -
 .../org/htrace/TestHTraceConfiguration.java     |   62 -
 .../src/test/java/org/htrace/TestSampler.java   |   49 -
 .../src/test/java/org/htrace/TraceCreator.java  |  157 --
 htrace-hbase/README.md                          |   12 +-
 htrace-hbase/pom.xml                            |    8 +-
 .../apache/htrace/impl/HBaseSpanReceiver.java   |  373 +++
 .../htrace/protobuf/generated/SpanProtos.java   | 2241 ++++++++++++++++++
 .../apache/htrace/viewer/HBaseSpanViewer.java   |  226 ++
 .../htrace/viewer/HBaseSpanViewerServer.java    |  115 +
 .../viewer/HBaseSpanViewerSpansServlet.java     |   97 +
 .../viewer/HBaseSpanViewerTracesServlet.java    |   84 +
 .../java/org/htrace/impl/HBaseSpanReceiver.java |  367 ---
 .../htrace/protobuf/generated/SpanProtos.java   | 2241 ------------------
 .../java/org/htrace/viewer/HBaseSpanViewer.java |  224 --
 .../htrace/viewer/HBaseSpanViewerServer.java    |  115 -
 .../viewer/HBaseSpanViewerSpansServlet.java     |   95 -
 .../viewer/HBaseSpanViewerTracesServlet.java    |   82 -
 htrace-hbase/src/main/protobuf/Span.proto       |    2 +-
 htrace-hbase/src/main/webapps/htrace/spans.js   |    2 +-
 .../org/apache/htrace/impl/HBaseTestUtil.java   |   89 +
 .../htrace/impl/TestHBaseSpanReceiver.java      |  226 ++
 .../htrace/viewer/TestHBaseSpanViewer.java      |   97 +
 .../java/org/htrace/impl/HBaseTestUtil.java     |   84 -
 .../org/htrace/impl/TestHBaseSpanReceiver.java  |  219 --
 .../org/htrace/viewer/TestHBaseSpanViewer.java  |   95 -
 htrace-zipkin/pom.xml                           |    4 +-
 .../apache/htrace/impl/ZipkinSpanReceiver.java  |  363 +++
 .../htrace/zipkin/HTraceToZipkinConverter.java  |  195 ++
 .../org/htrace/impl/ZipkinSpanReceiver.java     |  362 ---
 .../htrace/zipkin/HTraceToZipkinConverter.java  |  194 --
 .../htrace/TestHTraceSpanToZipkinSpan.java      |  135 ++
 .../org/htrace/TestHTraceSpanToZipkinSpan.java  |  132 --
 pom.xml                                         |    2 +-
 90 files changed, 6514 insertions(+), 6466 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 442609a..2e01807 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,10 @@ HTrace
 ======
 HTrace is a tracing framework intended for use with distributed systems written in java.
 
-The project is hosted at http://github.com/cloudera/htrace.
-The project is available in Maven Central with groupId: org.htrace, and name: htrace.
-(It was formally at groupId: org.cloudera.htrace, and name: htrace).
+The project is hosted at http://htrace.incubator.apache.org
+The project is available in Maven Central with groupId: org.apache.htrace,
+and name: htrace (It was formally groupId: org.cloudera.htrace, and
+groundId: org.htrace).
 
 API
 ---

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/pom.xml
----------------------------------------------------------------------
diff --git a/htrace-core/pom.xml b/htrace-core/pom.xml
index 47677d8..42f624c 100644
--- a/htrace-core/pom.xml
+++ b/htrace-core/pom.xml
@@ -17,7 +17,7 @@ language governing permissions and limitations under the License. -->
 
   <parent>
     <artifactId>htrace</artifactId>
-    <groupId>org.htrace</groupId>
+    <groupId>org.apache.htrace</groupId>
     <version>3.0.4</version>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/HTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/HTraceConfiguration.java b/htrace-core/src/main/java/org/apache/htrace/HTraceConfiguration.java
new file mode 100644
index 0000000..ecef911
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/HTraceConfiguration.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Wrapper which integrating applications should implement in order
+ * to provide tracing configuration.
+ */
+public abstract class HTraceConfiguration {
+
+  private static final Log LOG = LogFactory.getLog(HTraceConfiguration.class);
+
+  public static HTraceConfiguration fromMap(Map<String, String> conf) {
+    return new MapConf(conf);
+  }
+
+  public abstract String get(String key);
+
+  public abstract String get(String key, String defaultValue);
+
+  public boolean getBoolean(String key, boolean defaultValue) {
+    String value = get(key, String.valueOf(defaultValue)).trim().toLowerCase();
+
+    if ("true".equals(value)) {
+      return true;
+    } else if ("false".equals(value)) {
+      return false;
+    }
+
+    LOG.warn("Expected boolean for key [" + key + "] instead got [" + value + "].");
+    return defaultValue;
+  }
+
+  public int getInt(String key, int defaultVal) {
+    String val = get(key);
+    if (val == null || val.trim().isEmpty()) {
+      return defaultVal;
+    }
+    try {
+      return Integer.parseInt(val);
+    } catch (NumberFormatException nfe) {
+      throw new IllegalArgumentException("Bad value for '" + key + "': should be int");
+    }
+  }
+
+  private static class MapConf extends HTraceConfiguration {
+    private final Map<String, String> conf;
+
+    public MapConf(Map<String, String> conf) {
+      this.conf = new HashMap<String, String>(conf);
+    }
+
+    @Override
+    public String get(String key) {
+      return conf.get(key);
+    }
+
+    @Override
+    public String get(String key, String defaultValue) {
+      String value = get(key);
+      return value == null ? defaultValue : value;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/NullScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/NullScope.java b/htrace-core/src/main/java/org/apache/htrace/NullScope.java
new file mode 100644
index 0000000..32963a8
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/NullScope.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+/**
+ * Singleton instance representing an empty {@link TraceScope}.
+ */
+public final class NullScope extends TraceScope {
+
+  public static final TraceScope INSTANCE = new NullScope();
+
+  private NullScope() {
+    super(null, null);
+  }
+
+  @Override
+  public String toString() {
+    return "NullScope";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/Sampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/Sampler.java b/htrace-core/src/main/java/org/apache/htrace/Sampler.java
new file mode 100644
index 0000000..9f81e14
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/Sampler.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import org.apache.htrace.impl.AlwaysSampler;
+import org.apache.htrace.impl.NeverSampler;
+
+/**
+ * Extremely simple callback to determine the frequency that an action should be
+ * performed.
+ * <p/>
+ * 'T' is the object type you require to create a more advanced sampling
+ * function. For example if there is some RPC information in a 'Call' object,
+ * you might implement Sampler<Call>. Then when the RPC is received you can call
+ * one of the Trace.java functions that takes the extra 'info' parameter, which
+ * will be passed into the next function you implemented.
+ * <p/>
+ * For the example above, the next(T info) function may look like this
+ * <p/>
+ * public boolean next(T info){
+ * if (info == null) {
+ * return false;
+ * } else if (info.getName().equals("get")) {
+ * return Math.random() > 0.5;
+ * } else if (info.getName().equals("put")) {
+ * return Math.random() > 0.25;
+ * } else {
+ * return false;
+ * }
+ * }
+ * This would trace 50% of all gets, 75% of all puts and would not trace any other requests.
+ */
+public interface Sampler<T> {
+
+  public static final Sampler<?> ALWAYS = AlwaysSampler.INSTANCE;
+  public static final Sampler<?> NEVER = NeverSampler.INSTANCE;
+
+  public boolean next(T info);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/Span.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/Span.java b/htrace-core/src/main/java/org/apache/htrace/Span.java
new file mode 100644
index 0000000..633bcba
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/Span.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Base interface for gathering and reporting statistics about a block of
+ * execution.
+ * <p/>
+ * Spans form a tree structure with the parent relationship. The first span in a
+ * trace has no parent span.
+ */
+public interface Span {
+  public static final long ROOT_SPAN_ID = 0x74ace;
+
+  /**
+   * The block has completed, stop the clock
+   */
+  void stop();
+
+  /**
+   * Get the start time, in milliseconds
+   */
+  long getStartTimeMillis();
+
+  /**
+   * Get the stop time, in milliseconds
+   */
+  long getStopTimeMillis();
+
+  /**
+   * Return the total amount of time elapsed since start was called, if running,
+   * or difference between stop and start
+   */
+  long getAccumulatedMillis();
+
+  /**
+   * Has the span been started and not yet stopped?
+   */
+  boolean isRunning();
+
+  /**
+   * Return a textual description of this span
+   */
+  String getDescription();
+
+  /**
+   * A pseudo-unique (random) number assigned to this span instance
+   */
+  long getSpanId();
+
+  /**
+   * A pseudo-unique (random) number assigned to the trace associated with this
+   * span
+   */
+  long getTraceId();
+
+  /**
+   * Create a child span of this span with the given description
+   */
+  Span child(String description);
+
+  @Override
+  String toString();
+
+  /**
+   * Return the pseudo-unique (random) number of the parent span, returns
+   * ROOT_SPAN_ID if this is the root span
+   */
+  long getParentId();
+
+  /**
+   * Add a data annotation associated with this span
+   */
+  void addKVAnnotation(byte[] key, byte[] value);
+
+  /**
+   * Add a timeline annotation associated with this span
+   */
+  void addTimelineAnnotation(String msg);
+
+  /**
+   * Get data associated with this span (read only)
+   */
+  Map<byte[], byte[]> getKVAnnotations();
+
+  /**
+   * Get any timeline annotations (read only)
+   */
+  List<TimelineAnnotation> getTimelineAnnotations();
+
+  /**
+   * Return a unique id for the node or process from which this Span originated.
+   * IP address is a reasonable choice.
+   *
+   * @return
+   */
+  String getProcessId();
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/SpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/SpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/SpanReceiver.java
new file mode 100644
index 0000000..aad549a
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/SpanReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+
+import java.io.Closeable;
+
+
+/**
+ * The collector within a process that is the destination of Spans when a trace
+ * is running.
+ */
+public interface SpanReceiver extends Closeable {
+
+  /**
+   * Hosts of SpanReceivers should call this method to provide
+   * configuration to SpanReceivers after creating them.
+   */
+  public void configure(HTraceConfiguration conf);
+
+  /**
+   * Called when a Span is stopped and can now be stored.
+   *
+   * @param span
+   */
+  public void receiveSpan(Span span);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/TimelineAnnotation.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/TimelineAnnotation.java b/htrace-core/src/main/java/org/apache/htrace/TimelineAnnotation.java
new file mode 100644
index 0000000..d0ae675
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/TimelineAnnotation.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+public class TimelineAnnotation {
+  private final long time;
+  private final String msg;
+
+  public TimelineAnnotation(long time, String msg) {
+    this.time = time;
+    this.msg = msg;
+  }
+
+  public long getTime() {
+    return time;
+  }
+
+  public String getMessage() {
+    return msg;
+  }
+
+  @Override
+  public String toString() {
+    return "@" + time + ": " + msg;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/Trace.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/Trace.java b/htrace-core/src/main/java/org/apache/htrace/Trace.java
new file mode 100644
index 0000000..61dfdfa
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/Trace.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import org.apache.htrace.impl.MilliSpan;
+import org.apache.htrace.impl.TrueIfTracingSampler;
+import org.apache.htrace.wrappers.TraceCallable;
+import org.apache.htrace.wrappers.TraceRunnable;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.Callable;
+
+/**
+ * The primary way to interact with the library. Provides methods to start
+ * spans, as well as set necessary tracing information.
+ */
+public class Trace {
+  private final static Random random = new SecureRandom();
+
+  /**
+   * Starts and returns a new span as the child of the current span if the
+   * default sampler (TrueIfTracingSampler) returns true, otherwise returns the
+   * NullSpan.
+   *
+   * @param description Description of the span to be created.
+   * @return
+   */
+  public static TraceScope startSpan(String description) {
+    return startSpan(description, TrueIfTracingSampler.INSTANCE);
+  }
+
+  /**
+   * Starts and returns a new span as the child of the parameter 'parent'. This
+   * will always return a new span, even if tracing wasn't previously enabled for
+   * this thread.
+   *
+   * @param description Description of the span to be created.
+   * @param parent      The parent that should be used to create the child span that is to
+   *                    be returned.
+   * @return
+   */
+  public static TraceScope startSpan(String description, Span parent) {
+    if (parent == null) return startSpan(description);
+    return continueSpan(parent.child(description));
+  }
+
+  public static TraceScope startSpan(String description, TraceInfo tinfo) {
+    if (tinfo == null) return continueSpan(null);
+    Span newSpan = new MilliSpan(description, tinfo.traceId, tinfo.spanId,
+        random.nextLong(), Tracer.getProcessId());
+    return continueSpan(newSpan);
+  }
+
+  public static <T> TraceScope startSpan(String description, Sampler<T> s) {
+    return startSpan(description, s, null);
+  }
+
+  public static TraceScope startSpan(String description, Sampler<TraceInfo> s, TraceInfo tinfo) {
+    Span span = null;
+    if (isTracing() || s.next(tinfo)) {
+      span = new MilliSpan(description, tinfo.traceId, tinfo.spanId,
+          random.nextLong(), Tracer.getProcessId());
+    }
+    return continueSpan(span);
+  }
+
+  public static <T> TraceScope startSpan(String description, Sampler<T> s, T info) {
+    Span span = null;
+    if (isTracing() || s.next(info)) {
+      span = Tracer.getInstance().createNew(description);
+    }
+    return continueSpan(span);
+  }
+
+  /**
+   * Pick up an existing span from another thread.
+   */
+  public static TraceScope continueSpan(Span s) {
+    // Return an empty TraceScope that does nothing on close
+    if (s == null) return NullScope.INSTANCE;
+    return Tracer.getInstance().continueSpan(s);
+  }
+
+  /**
+   * Set the processId to be used for all Spans created by this Tracer.
+   *
+   * @param processId
+   * @see Span.java
+   */
+  public static void setProcessId(String processId) {
+    Tracer.processId = processId;
+  }
+
+  /**
+   * Removes the given SpanReceiver from the list of SpanReceivers.
+   *
+   * @param rcvr
+   */
+  public static void removeReceiver(SpanReceiver rcvr) {
+    Tracer.getInstance().removeReceiver(rcvr);
+  }
+
+  /**
+   * Adds the given SpanReceiver to the current Tracer instance's list of
+   * SpanReceivers.
+   *
+   * @param rcvr
+   */
+  public static void addReceiver(SpanReceiver rcvr) {
+    Tracer.getInstance().addReceiver(rcvr);
+  }
+
+  /**
+   * Adds a data annotation to the current span if tracing is currently on.
+   */
+  public static void addKVAnnotation(byte[] key, byte[] value) {
+    Span s = currentSpan();
+    if (s != null) {
+      s.addKVAnnotation(key, value);
+    }
+  }
+
+  /**
+   * Annotate the current span with the given message.
+   */
+  public static void addTimelineAnnotation(String msg) {
+    Span s = currentSpan();
+    if (s != null) {
+      s.addTimelineAnnotation(msg);
+    }
+  }
+
+  /**
+   * Returns true if the current thread is a part of a trace, false otherwise.
+   *
+   * @return
+   */
+  public static boolean isTracing() {
+    return Tracer.getInstance().isTracing();
+  }
+
+  /**
+   * If we are tracing, return the current span, else null
+   *
+   * @return Span representing the current trace, or null if not tracing.
+   */
+  public static Span currentSpan() {
+    return Tracer.getInstance().currentSpan();
+  }
+
+  /**
+   * Wrap the callable in a TraceCallable, if tracing.
+   *
+   * @param callable
+   * @return The callable provided, wrapped if tracing, 'callable' if not.
+   */
+  public static <V> Callable<V> wrap(Callable<V> callable) {
+    if (isTracing()) {
+      return new TraceCallable<V>(Trace.currentSpan(), callable);
+    } else {
+      return callable;
+    }
+  }
+
+  /**
+   * Wrap the runnable in a TraceRunnable, if tracing
+   *
+   * @param runnable
+   * @return The runnable provided, wrapped if tracing, 'runnable' if not.
+   */
+  public static Runnable wrap(Runnable runnable) {
+    if (isTracing()) {
+      return new TraceRunnable(Trace.currentSpan(), runnable);
+    } else {
+      return runnable;
+    }
+  }
+
+  /**
+   * Wrap the runnable in a TraceRunnable, if tracing
+   *
+   * @param description name of the span to be created.
+   * @param runnable
+   * @return The runnable provided, wrapped if tracing, 'runnable' if not.
+   */
+  public static Runnable wrap(String description, Runnable runnable) {
+    if (isTracing()) {
+      return new TraceRunnable(Trace.currentSpan(), runnable, description);
+    } else {
+      return runnable;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/TraceInfo.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/TraceInfo.java b/htrace-core/src/main/java/org/apache/htrace/TraceInfo.java
new file mode 100644
index 0000000..9e7d74a
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/TraceInfo.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+
+public class TraceInfo {
+  public final long traceId;
+  public final long spanId;
+
+  public TraceInfo(long traceId, long spanId) {
+    this.traceId = traceId;
+    this.spanId = spanId;
+  }
+
+  @Override
+  public String toString() {
+    return "TraceInfo(traceId=" + traceId + ", spanId=" + spanId + ")";
+  }
+
+  public static TraceInfo fromSpan(Span s) {
+    if (s == null) return null;
+    return new TraceInfo(s.getTraceId(), s.getSpanId());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/TraceScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/TraceScope.java b/htrace-core/src/main/java/org/apache/htrace/TraceScope.java
new file mode 100644
index 0000000..7773aad
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/TraceScope.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import java.io.Closeable;
+
+public class TraceScope implements Closeable {
+
+  /**
+   * the span for this scope
+   */
+  private final Span span;
+
+  /**
+   * the span that was "current" before this scope was entered
+   */
+  private final Span savedSpan;
+
+  private boolean detached = false;
+
+  TraceScope(Span span, Span saved) {
+    this.span = span;
+    this.savedSpan = saved;
+  }
+
+  public Span getSpan() {
+    return span;
+  }
+
+  /**
+   * Remove this span as the current thread, but don't stop it yet or
+   * send it for collection. This is useful if the span object is then
+   * passed to another thread for use with Trace.continueTrace().
+   *
+   * @return the same Span object
+   */
+  public Span detach() {
+    detached = true;
+
+    Span cur = Tracer.getInstance().currentSpan();
+    if (cur != span) {
+      Tracer.LOG.debug("Closing trace span " + span + " but " +
+          cur + " was top-of-stack");
+    } else {
+      Tracer.getInstance().setCurrentSpan(savedSpan);
+    }
+    return span;
+  }
+
+  /**
+   * Return true when {@link #detach()} has been called. Helpful when debugging
+   * multiple threads working on a single span.
+   */
+  public boolean isDetached() {
+    return detached;
+  }
+
+  @Override
+  public void close() {
+    if (span == null) return;
+
+    if (!detached) {
+      // The span is done
+      span.stop();
+      detach();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/TraceTree.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/TraceTree.java b/htrace-core/src/main/java/org/apache/htrace/TraceTree.java
new file mode 100644
index 0000000..8dc6a30
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/TraceTree.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Collection;
+
+/**
+ * Used to create the graph formed by spans.
+ */
+public class TraceTree {
+  public static final Log LOG = LogFactory.getLog(Tracer.class);
+  private Multimap<Long, Span> spansByParentID;
+  private Collection<Span> spans;
+  private Multimap<String, Span> spansByPid;
+
+  /**
+   * Create a new TraceTree
+   *
+   * @param spans The collection of spans to use to create this TraceTree. Should
+   *              have at least one root span (span with parentId =
+   *              Span.ROOT_SPAN_ID
+   */
+  public TraceTree(Collection<Span> spans) {
+    this.spans = ImmutableList.copyOf(spans);
+    this.spansByParentID = HashMultimap.<Long, Span>create();
+    this.spansByPid = HashMultimap.<String, Span>create();
+
+    for (Span s : this.spans) {
+      if (s.getProcessId() != null) {
+        spansByPid.put(s.getProcessId(), s);
+      } else {
+        LOG.warn("Encountered span with null processId. This should not happen. Span: "
+            + s);
+      }
+      spansByParentID.put(s.getParentId(), s);
+    }
+  }
+
+  /**
+   * @return The collection of spans given to this TraceTree at construction.
+   */
+  public Collection<Span> getSpans() {
+    return spans;
+  }
+
+  /**
+   * @return A copy of the MultiMap from parent span ID -> children of span with
+   *         that ID.
+   */
+  public Multimap<Long, Span> getSpansByParentIdMap() {
+    return HashMultimap.<Long, Span>create(spansByParentID);
+  }
+
+  /**
+   * @return A collection of the root spans (spans with parent ID =
+   *         Span.ROOT_SPAN_ID) in this tree.
+   */
+  public Collection<Span> getRoots() {
+    Collection<Span> roots = spansByParentID.get(Span.ROOT_SPAN_ID);
+    if (roots != null) {
+      return roots;
+    }
+    throw new IllegalStateException(
+        "TraceTree is not correctly formed - there are no root spans in the collection provided at construction.");
+  }
+
+  /**
+   * @return A copy of the Multimap from String process ID -> spans with that
+   *         process ID. If process ID was not set in Trace.java, all spans will
+   *         have empty string process IDs.
+   */
+  public Multimap<String, Span> getSpansByPidMap() {
+    return HashMultimap.<String, Span>create(spansByPid);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/Tracer.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/Tracer.java b/htrace-core/src/main/java/org/apache/htrace/Tracer.java
new file mode 100644
index 0000000..614521c
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/Tracer.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.htrace.impl.MilliSpan;
+
+import java.security.SecureRandom;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * A Tracer provides the implementation for collecting and distributing Spans
+ * within a process.
+ */
+public class Tracer {
+  public static final Log LOG = LogFactory.getLog(Tracer.class);
+  private final static Random random = new SecureRandom();
+  private final List<SpanReceiver> receivers = new CopyOnWriteArrayList<SpanReceiver>();
+  private static final ThreadLocal<Span> currentSpan = new ThreadLocal<Span>() {
+    @Override
+    protected Span initialValue() {
+      return null;
+    }
+  };
+  public static final TraceInfo DONT_TRACE = new TraceInfo(-1, -1);
+  protected static String processId = null;
+
+  /**
+   * Internal class for defered singleton idiom.
+   * <p/>
+   * https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
+   */
+  private static class TracerHolder {
+    private static final Tracer INSTANCE = new Tracer();
+  }
+
+  public static Tracer getInstance() {
+    return TracerHolder.INSTANCE;
+  }
+
+  protected Span createNew(String description) {
+    Span parent = currentSpan.get();
+    if (parent == null) {
+      return new MilliSpan(description,
+          /* traceId = */ random.nextLong(),
+          /* parentSpanId = */ Span.ROOT_SPAN_ID,
+          /* spanId = */ random.nextLong(),
+          getProcessId());
+    } else {
+      return parent.child(description);
+    }
+  }
+
+  protected boolean isTracing() {
+    return currentSpan.get() != null;
+  }
+
+  protected Span currentSpan() {
+    return currentSpan.get();
+  }
+
+  public void deliver(Span span) {
+    for (SpanReceiver receiver : receivers) {
+      receiver.receiveSpan(span);
+    }
+  }
+
+  protected void addReceiver(SpanReceiver receiver) {
+    receivers.add(receiver);
+  }
+
+  protected void removeReceiver(SpanReceiver receiver) {
+    receivers.remove(receiver);
+  }
+
+  protected Span setCurrentSpan(Span span) {
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("setting current span " + span);
+    }
+    currentSpan.set(span);
+    return span;
+  }
+
+
+  public TraceScope continueSpan(Span s) {
+    Span oldCurrent = currentSpan();
+    setCurrentSpan(s);
+    return new TraceScope(s, oldCurrent);
+  }
+
+  protected int numReceivers() {
+    return receivers.size();
+  }
+
+  static String getProcessId() {
+    if (processId == null) {
+      String cmdLine = System.getProperty("sun.java.command");
+      if (cmdLine != null && !cmdLine.isEmpty()) {
+        String fullClassName = cmdLine.split("\\s+")[0];
+        String[] classParts = fullClassName.split("\\.");
+        cmdLine = classParts[classParts.length - 1];
+      }
+
+      processId = (cmdLine == null || cmdLine.isEmpty()) ? "Unknown" : cmdLine;
+    }
+    return processId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/AlwaysSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/AlwaysSampler.java b/htrace-core/src/main/java/org/apache/htrace/impl/AlwaysSampler.java
new file mode 100644
index 0000000..8c90eff
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/AlwaysSampler.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.Sampler;
+
+public final class AlwaysSampler implements Sampler<Object> {
+
+  public static final AlwaysSampler INSTANCE = new AlwaysSampler();
+
+  private AlwaysSampler() {
+  }
+
+  @Override
+  public boolean next(Object info) {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/CountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/CountSampler.java b/htrace-core/src/main/java/org/apache/htrace/impl/CountSampler.java
new file mode 100644
index 0000000..78e155c
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/CountSampler.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.Sampler;
+
+import java.util.Random;
+
+/**
+ * Sampler that returns true every N calls.
+ */
+public class CountSampler implements Sampler<Object> {
+
+  final static Random random = new Random();
+
+  final long frequency;
+  long count = random.nextLong();
+
+  public CountSampler(long frequency) {
+    this.frequency = frequency;
+  }
+
+  @Override
+  public boolean next(Object info) {
+    return (count++ % frequency) == 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/LocalFileSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/LocalFileSpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/impl/LocalFileSpanReceiver.java
new file mode 100644
index 0000000..6b4be80
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/LocalFileSpanReceiver.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+import org.mortbay.util.ajax.JSON;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Writes the spans it receives to a local file.
+ * A production LocalFileSpanReceiver should use a real CSV format.
+ */
+public class LocalFileSpanReceiver implements SpanReceiver {
+  public static final Log LOG = LogFactory.getLog(LocalFileSpanReceiver.class);
+  public static final String PATH_KEY = "local-file-span-receiver.path";
+  public static final String CAPACITY_KEY = "local-file-span-receiver.capacity";
+  // default capacity for the executors blocking queue
+  public static final int CAPACITY_DEFAULT = 5000;
+  // default timeout duration when calling executor.awaitTermination()
+  public static final long EXECUTOR_TERMINATION_TIMEOUT_DURATION_DEFAULT = 60;
+  private String file;
+  private FileWriter fwriter;
+  private BufferedWriter bwriter;
+  private Map<String, Object> values;
+  private ExecutorService executor;
+  private long executorTerminationTimeoutDuration;
+
+  public LocalFileSpanReceiver() {
+  }
+
+
+  @Override
+  public void configure(HTraceConfiguration conf) {
+    this.executorTerminationTimeoutDuration = EXECUTOR_TERMINATION_TIMEOUT_DURATION_DEFAULT;
+    int capacity = conf.getInt(CAPACITY_KEY, CAPACITY_DEFAULT);
+    this.file = conf.get(PATH_KEY);
+    if (file == null || file.isEmpty()) {
+      throw new IllegalArgumentException("must configure " + PATH_KEY);
+    }
+    this.executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS,
+        new LinkedBlockingQueue<Runnable>(capacity));
+    try {
+      this.fwriter = new FileWriter(this.file, true);
+    } catch (IOException ioe) {
+      throw new RuntimeException(ioe);
+    }
+    this.bwriter = new BufferedWriter(fwriter);
+    this.values = new LinkedHashMap<String, Object>();
+  }
+
+
+  private class WriteSpanRunnable implements Runnable {
+    public final Span span;
+
+    public WriteSpanRunnable(Span span) {
+      this.span = span;
+    }
+
+    @Override
+    public void run() {
+      try {
+        values.put("TraceID", span.getTraceId());
+        values.put("SpanID", span.getSpanId());
+        values.put("ParentID", span.getParentId());
+        values.put("ProcessID", span.getProcessId());
+        values.put("Start", span.getStartTimeMillis());
+        values.put("Stop", span.getStopTimeMillis());
+        values.put("Description", span.getDescription());
+        values.put("KVAnnotations", span.getKVAnnotations());
+        values.put("TLAnnotations", span.getTimelineAnnotations());
+        bwriter.write(JSON.toString(values));
+        bwriter.newLine();
+        bwriter.flush();
+        values.clear();
+      } catch (IOException e) {
+        LOG.error("Error when writing to file: " + file, e);
+      }
+    }
+  }
+
+  @Override
+  public void receiveSpan(Span span) {
+    executor.submit(new WriteSpanRunnable(span));
+  }
+
+  @Override
+  public void close() throws IOException {
+    executor.shutdown();
+    try {
+      if (!executor.awaitTermination(this.executorTerminationTimeoutDuration,
+          TimeUnit.SECONDS)) {
+        LOG.warn("Was not able to process all remaining spans to write upon closing in: "
+            + this.executorTerminationTimeoutDuration + "s");
+      }
+    } catch (InterruptedException e1) {
+      LOG.warn("Thread interrupted when terminating executor.", e1);
+    }
+
+    try {
+      fwriter.close();
+    } catch (IOException e) {
+      LOG.error("Error closing filewriter for file: " + file, e);
+    }
+    try {
+      bwriter.close();
+    } catch (IOException e) {
+      LOG.error("Error closing bufferedwriter for file: " + file, e);
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java b/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java
new file mode 100644
index 0000000..9d24f68
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.Span;
+import org.apache.htrace.TimelineAnnotation;
+import org.apache.htrace.Tracer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * A Span implementation that stores its information in milliseconds since the
+ * epoch.
+ */
+public class MilliSpan implements Span {
+
+  private static Random rand = new Random();
+
+  private long start;
+  private long stop;
+  private final String description;
+  private final long traceId;
+  private final long parentSpanId;
+  private final long spanId;
+  private Map<byte[], byte[]> traceInfo = null;
+  private final String processId;
+  private List<TimelineAnnotation> timeline = null;
+
+  @Override
+  public Span child(String description) {
+    return new MilliSpan(description, traceId, spanId, rand.nextLong(), processId);
+  }
+
+  public MilliSpan(String description, long traceId, long parentSpanId, long spanId, String processId) {
+    this.description = description;
+    this.traceId = traceId;
+    this.parentSpanId = parentSpanId;
+    this.spanId = spanId;
+    this.start = System.currentTimeMillis();
+    this.stop = 0;
+    this.processId = processId;
+  }
+
+  @Override
+  public synchronized void stop() {
+    if (stop == 0) {
+      if (start == 0)
+        throw new IllegalStateException("Span for " + description
+            + " has not been started");
+      stop = System.currentTimeMillis();
+      Tracer.getInstance().deliver(this);
+    }
+  }
+
+  protected long currentTimeMillis() {
+    return System.currentTimeMillis();
+  }
+
+  @Override
+  public synchronized boolean isRunning() {
+    return start != 0 && stop == 0;
+  }
+
+  @Override
+  public synchronized long getAccumulatedMillis() {
+    if (start == 0)
+      return 0;
+    if (stop > 0)
+      return stop - start;
+    return currentTimeMillis() - start;
+  }
+
+  @Override
+  public String toString() {
+    return String.format("Span{Id:0x%16x,parentId:0x%16x,desc:%s}", spanId, parentSpanId, description);
+  }
+
+  @Override
+  public String getDescription() {
+    return description;
+  }
+
+  @Override
+  public long getSpanId() {
+    return spanId;
+  }
+
+  @Override
+  public long getParentId() {
+    return parentSpanId;
+  }
+
+  @Override
+  public long getTraceId() {
+    return traceId;
+  }
+
+  @Override
+  public long getStartTimeMillis() {
+    return start;
+  }
+
+  @Override
+  public long getStopTimeMillis() {
+    return stop;
+  }
+
+  @Override
+  public void addKVAnnotation(byte[] key, byte[] value) {
+    if (traceInfo == null)
+      traceInfo = new HashMap<byte[], byte[]>();
+    traceInfo.put(key, value);
+  }
+
+  @Override
+  public void addTimelineAnnotation(String msg) {
+    if (timeline == null) {
+      timeline = new ArrayList<TimelineAnnotation>();
+    }
+    timeline.add(new TimelineAnnotation(System.currentTimeMillis(), msg));
+  }
+
+  @Override
+  public Map<byte[], byte[]> getKVAnnotations() {
+    if (traceInfo == null)
+      return Collections.emptyMap();
+    return Collections.unmodifiableMap(traceInfo);
+  }
+
+  @Override
+  public List<TimelineAnnotation> getTimelineAnnotations() {
+    if (timeline == null) {
+      return Collections.emptyList();
+    }
+    return Collections.unmodifiableList(timeline);
+  }
+
+  @Override
+  public String getProcessId() {
+    return processId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/NeverSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/NeverSampler.java b/htrace-core/src/main/java/org/apache/htrace/impl/NeverSampler.java
new file mode 100644
index 0000000..20233d9
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/NeverSampler.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.Sampler;
+
+public final class NeverSampler implements Sampler<Object> {
+
+  public static final NeverSampler INSTANCE = new NeverSampler();
+
+  private NeverSampler() {
+  }
+
+  @Override
+  public boolean next(Object info) {
+    return false;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/POJOSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/POJOSpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/impl/POJOSpanReceiver.java
new file mode 100644
index 0000000..a77fd39
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/POJOSpanReceiver.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * SpanReceiver for testing only that just collects the Span objects it
+ * receives. The spans it receives can be accessed with getSpans();
+ */
+public class POJOSpanReceiver implements SpanReceiver {
+  private final Collection<Span> spans;
+
+  @Override
+  public void configure(HTraceConfiguration conf) {
+  }
+
+  /**
+   * @return The spans this POJOSpanReceiver has received.
+   */
+  public Collection<Span> getSpans() {
+    return spans;
+  }
+
+  public POJOSpanReceiver() {
+    this.spans = new HashSet<Span>();
+  }
+
+  @Override
+  public void close() throws IOException {
+  }
+
+  @Override
+  public void receiveSpan(Span span) {
+    spans.add(span);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/ProbabilitySampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/ProbabilitySampler.java b/htrace-core/src/main/java/org/apache/htrace/impl/ProbabilitySampler.java
new file mode 100644
index 0000000..a34c5ec
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/ProbabilitySampler.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.Sampler;
+
+import java.util.Random;
+
+public class ProbabilitySampler implements Sampler<Object> {
+  public final double threshold;
+  private Random random;
+
+  public ProbabilitySampler(double threshold) {
+    this.threshold = threshold;
+    random = new Random();
+  }
+
+  @Override
+  public boolean next(Object info) {
+    return random.nextDouble() < threshold;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/StandardOutSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/StandardOutSpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/impl/StandardOutSpanReceiver.java
new file mode 100644
index 0000000..2253f86
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/StandardOutSpanReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+
+import java.io.IOException;
+
+/**
+ * Used for testing. Simply prints to standard out any spans it receives.
+ */
+public class StandardOutSpanReceiver implements SpanReceiver {
+
+  @Override
+  public void configure(HTraceConfiguration conf) {
+  }
+
+  @Override
+  public void receiveSpan(Span span) {
+    System.out.println(span);
+  }
+
+  @Override
+  public void close() throws IOException {
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/impl/TrueIfTracingSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/TrueIfTracingSampler.java b/htrace-core/src/main/java/org/apache/htrace/impl/TrueIfTracingSampler.java
new file mode 100644
index 0000000..69598ba
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/TrueIfTracingSampler.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.impl;
+
+import org.apache.htrace.Sampler;
+import org.apache.htrace.Trace;
+
+/**
+ * A Sampler that returns true if and only if tracing is on the current thread.
+ */
+public class TrueIfTracingSampler implements Sampler<Object> {
+
+  public static final TrueIfTracingSampler INSTANCE = new TrueIfTracingSampler();
+
+  private TrueIfTracingSampler() {
+  }
+
+  @Override
+  public boolean next(Object info) {
+    return Trace.isTracing();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceCallable.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceCallable.java b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceCallable.java
new file mode 100644
index 0000000..e761fbf
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceCallable.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.wrappers;
+
+import org.apache.htrace.Span;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Wrap a Callable with a Span that survives a change in threads.
+ */
+public class TraceCallable<V> implements Callable<V> {
+  private final Callable<V> impl;
+  private final Span parent;
+  private final String description;
+
+  public TraceCallable(Callable<V> impl) {
+    this(Trace.currentSpan(), impl);
+  }
+
+  public TraceCallable(Span parent, Callable<V> impl) {
+    this(parent, impl, null);
+  }
+
+  public TraceCallable(Span parent, Callable<V> impl, String description) {
+    this.impl = impl;
+    this.parent = parent;
+    this.description = description;
+  }
+
+  @Override
+  public V call() throws Exception {
+    if (parent != null) {
+      TraceScope chunk = Trace.startSpan(getDescription(), parent);
+
+      try {
+        return impl.call();
+      } finally {
+        chunk.close();
+      }
+    } else {
+      return impl.call();
+    }
+  }
+
+  public Callable<V> getImpl() {
+    return impl;
+  }
+
+  private String getDescription() {
+    return this.description == null ? Thread.currentThread().getName() : description;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceExecutorService.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceExecutorService.java b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceExecutorService.java
new file mode 100644
index 0000000..03e891f
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceExecutorService.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.wrappers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+
+public class TraceExecutorService implements ExecutorService {
+
+  private final ExecutorService impl;
+
+  public TraceExecutorService(ExecutorService impl) {
+    this.impl = impl;
+  }
+
+  @Override
+  public void execute(Runnable command) {
+    impl.execute(new TraceRunnable(command));
+  }
+
+  @Override
+  public void shutdown() {
+    impl.shutdown();
+  }
+
+  @Override
+  public List<Runnable> shutdownNow() {
+    return impl.shutdownNow();
+  }
+
+  @Override
+  public boolean isShutdown() {
+    return impl.isShutdown();
+  }
+
+  @Override
+  public boolean isTerminated() {
+    return impl.isTerminated();
+  }
+
+  @Override
+  public boolean awaitTermination(long timeout, TimeUnit unit)
+      throws InterruptedException {
+    return impl.awaitTermination(timeout, unit);
+  }
+
+  @Override
+  public <T> Future<T> submit(Callable<T> task) {
+    return impl.submit(new TraceCallable<T>(task));
+  }
+
+  @Override
+  public <T> Future<T> submit(Runnable task, T result) {
+    return impl.submit(new TraceRunnable(task), result);
+  }
+
+  @Override
+  public Future<?> submit(Runnable task) {
+    return impl.submit(new TraceRunnable(task));
+  }
+
+  private <T> Collection<? extends Callable<T>> wrapCollection(
+      Collection<? extends Callable<T>> tasks) {
+    List<Callable<T>> result = new ArrayList<Callable<T>>();
+    for (Callable<T> task : tasks) {
+      result.add(new TraceCallable<T>(task));
+    }
+    return result;
+  }
+
+  @Override
+  public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+      throws InterruptedException {
+    return impl.invokeAll(wrapCollection(tasks));
+  }
+
+  @Override
+  public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+                                       long timeout, TimeUnit unit) throws InterruptedException {
+    return impl.invokeAll(wrapCollection(tasks), timeout, unit);
+  }
+
+  @Override
+  public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+      throws InterruptedException, ExecutionException {
+    return impl.invokeAny(wrapCollection(tasks));
+  }
+
+  @Override
+  public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout,
+                         TimeUnit unit) throws InterruptedException, ExecutionException,
+      TimeoutException {
+    return impl.invokeAny(wrapCollection(tasks), timeout, unit);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceProxy.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceProxy.java b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceProxy.java
new file mode 100644
index 0000000..c06befd
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceProxy.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.wrappers;
+
+import org.apache.htrace.Sampler;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+public class TraceProxy {
+  /**
+   * Returns an object that will trace all calls to itself.
+   *
+   * @param instance
+   * @return
+   */
+  public static <T> T trace(T instance) {
+    return trace(instance, Sampler.ALWAYS);
+  }
+
+  /**
+   * Returns an object that will trace all calls to itself.
+   *
+   * @param <V>
+   * @param instance
+   * @param sampler
+   * @return
+   */
+  @SuppressWarnings("unchecked")
+  public static <T, V> T trace(final T instance, final Sampler<V> sampler) {
+    InvocationHandler handler = new InvocationHandler() {
+      @Override
+      public Object invoke(Object obj, Method method, Object[] args)
+          throws Throwable {
+        if (!sampler.next(null)) {
+          return method.invoke(instance, args);
+        }
+
+        TraceScope scope = Trace.startSpan(method.getName(), Sampler.ALWAYS);
+        try {
+          return method.invoke(instance, args);
+        } catch (Throwable ex) {
+          ex.printStackTrace();
+          throw ex;
+        } finally {
+          scope.close();
+        }
+      }
+    };
+    return (T) Proxy.newProxyInstance(instance.getClass().getClassLoader(),
+        instance.getClass().getInterfaces(), handler);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceRunnable.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceRunnable.java b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceRunnable.java
new file mode 100644
index 0000000..64fada7
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/wrappers/TraceRunnable.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.wrappers;
+
+import org.apache.htrace.Span;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
+
+/**
+ * Wrap a Runnable with a Span that survives a change in threads.
+ */
+public class TraceRunnable implements Runnable {
+
+  private final Span parent;
+  private final Runnable runnable;
+  private final String description;
+
+  public TraceRunnable(Runnable runnable) {
+    this(Trace.currentSpan(), runnable);
+  }
+
+  public TraceRunnable(Span parent, Runnable runnable) {
+    this(parent, runnable, null);
+  }
+
+  public TraceRunnable(Span parent, Runnable runnable, String description) {
+    this.parent = parent;
+    this.runnable = runnable;
+    this.description = description;
+  }
+
+  @Override
+  public void run() {
+    if (parent != null) {
+      TraceScope chunk = Trace.startSpan(getDescription(), parent);
+
+      try {
+        runnable.run();
+      } finally {
+        chunk.close();
+      }
+    } else {
+      runnable.run();
+    }
+  }
+
+  private String getDescription() {
+    return this.description == null ? Thread.currentThread().getName() : description;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/HTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/HTraceConfiguration.java b/htrace-core/src/main/java/org/htrace/HTraceConfiguration.java
deleted file mode 100644
index 7ad608f..0000000
--- a/htrace-core/src/main/java/org/htrace/HTraceConfiguration.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Wrapper which integrating applications should implement in order
- * to provide tracing configuration.
- */
-public abstract class HTraceConfiguration {
-
-  private static final Log LOG = LogFactory.getLog(HTraceConfiguration.class);
-
-  public static HTraceConfiguration fromMap(Map<String, String> conf) {
-    return new MapConf(conf);
-  }
-
-  public abstract String get(String key);
-
-  public abstract String get(String key, String defaultValue);
-
-  public boolean getBoolean(String key, boolean defaultValue) {
-    String value = get(key, String.valueOf(defaultValue)).trim().toLowerCase();
-
-    if ("true".equals(value)) {
-      return true;
-    } else if ("false".equals(value)) {
-      return false;
-    }
-
-    LOG.warn("Expected boolean for key [" + key + "] instead got [" + value + "].");
-    return defaultValue;
-  }
-
-  public int getInt(String key, int defaultVal) {
-    String val = get(key);
-    if (val == null || val.trim().isEmpty()) {
-      return defaultVal;
-    }
-    try {
-      return Integer.parseInt(val);
-    } catch (NumberFormatException nfe) {
-      throw new IllegalArgumentException("Bad value for '" + key + "': should be int");
-    }
-  }
-
-  private static class MapConf extends HTraceConfiguration {
-    private final Map<String, String> conf;
-
-    public MapConf(Map<String, String> conf) {
-      this.conf = new HashMap<String, String>(conf);
-    }
-
-    @Override
-    public String get(String key) {
-      return conf.get(key);
-    }
-
-    @Override
-    public String get(String key, String defaultValue) {
-      String value = get(key);
-      return value == null ? defaultValue : value;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/NullScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/NullScope.java b/htrace-core/src/main/java/org/htrace/NullScope.java
deleted file mode 100644
index 1f90156..0000000
--- a/htrace-core/src/main/java/org/htrace/NullScope.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-/**
- * Singleton instance representing an empty {@link TraceScope}.
- */
-public final class NullScope extends TraceScope {
-
-  public static final TraceScope INSTANCE = new NullScope();
-
-  private NullScope() {
-    super(null, null);
-  }
-
-  @Override
-  public String toString() {
-    return "NullScope";
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/Sampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/Sampler.java b/htrace-core/src/main/java/org/htrace/Sampler.java
deleted file mode 100644
index 08c520d..0000000
--- a/htrace-core/src/main/java/org/htrace/Sampler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import org.htrace.impl.AlwaysSampler;
-import org.htrace.impl.NeverSampler;
-
-/**
- * Extremely simple callback to determine the frequency that an action should be
- * performed.
- * <p/>
- * 'T' is the object type you require to create a more advanced sampling
- * function. For example if there is some RPC information in a 'Call' object,
- * you might implement Sampler<Call>. Then when the RPC is received you can call
- * one of the Trace.java functions that takes the extra 'info' parameter, which
- * will be passed into the next function you implemented.
- * <p/>
- * For the example above, the next(T info) function may look like this
- * <p/>
- * public boolean next(T info){
- * if (info == null) {
- * return false;
- * } else if (info.getName().equals("get")) {
- * return Math.random() > 0.5;
- * } else if (info.getName().equals("put")) {
- * return Math.random() > 0.25;
- * } else {
- * return false;
- * }
- * }
- * This would trace 50% of all gets, 75% of all puts and would not trace any other requests.
- */
-public interface Sampler<T> {
-
-  public static final Sampler<?> ALWAYS = AlwaysSampler.INSTANCE;
-  public static final Sampler<?> NEVER = NeverSampler.INSTANCE;
-
-  public boolean next(T info);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/Span.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/Span.java b/htrace-core/src/main/java/org/htrace/Span.java
deleted file mode 100644
index d7d0d9a..0000000
--- a/htrace-core/src/main/java/org/htrace/Span.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import java.util.List;
-import java.util.Map;
-
-
-/**
- * Base interface for gathering and reporting statistics about a block of
- * execution.
- * <p/>
- * Spans form a tree structure with the parent relationship. The first span in a
- * trace has no parent span.
- */
-public interface Span {
-  public static final long ROOT_SPAN_ID = 0x74ace;
-
-  /**
-   * The block has completed, stop the clock
-   */
-  void stop();
-
-  /**
-   * Get the start time, in milliseconds
-   */
-  long getStartTimeMillis();
-
-  /**
-   * Get the stop time, in milliseconds
-   */
-  long getStopTimeMillis();
-
-  /**
-   * Return the total amount of time elapsed since start was called, if running,
-   * or difference between stop and start
-   */
-  long getAccumulatedMillis();
-
-  /**
-   * Has the span been started and not yet stopped?
-   */
-  boolean isRunning();
-
-  /**
-   * Return a textual description of this span
-   */
-  String getDescription();
-
-  /**
-   * A pseudo-unique (random) number assigned to this span instance
-   */
-  long getSpanId();
-
-  /**
-   * A pseudo-unique (random) number assigned to the trace associated with this
-   * span
-   */
-  long getTraceId();
-
-  /**
-   * Create a child span of this span with the given description
-   */
-  Span child(String description);
-
-  @Override
-  String toString();
-
-  /**
-   * Return the pseudo-unique (random) number of the parent span, returns
-   * ROOT_SPAN_ID if this is the root span
-   */
-  long getParentId();
-
-  /**
-   * Add a data annotation associated with this span
-   */
-  void addKVAnnotation(byte[] key, byte[] value);
-
-  /**
-   * Add a timeline annotation associated with this span
-   */
-  void addTimelineAnnotation(String msg);
-
-  /**
-   * Get data associated with this span (read only)
-   */
-  Map<byte[], byte[]> getKVAnnotations();
-
-  /**
-   * Get any timeline annotations (read only)
-   */
-  List<TimelineAnnotation> getTimelineAnnotations();
-
-  /**
-   * Return a unique id for the node or process from which this Span originated.
-   * IP address is a reasonable choice.
-   *
-   * @return
-   */
-  String getProcessId();
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/SpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/SpanReceiver.java b/htrace-core/src/main/java/org/htrace/SpanReceiver.java
deleted file mode 100644
index 65cfb45..0000000
--- a/htrace-core/src/main/java/org/htrace/SpanReceiver.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-
-import java.io.Closeable;
-
-
-/**
- * The collector within a process that is the destination of Spans when a trace
- * is running.
- */
-public interface SpanReceiver extends Closeable {
-
-  /**
-   * Hosts of SpanReceivers should call this method to provide
-   * configuration to SpanReceivers after creating them.
-   */
-  public void configure(HTraceConfiguration conf);
-
-  /**
-   * Called when a Span is stopped and can now be stored.
-   *
-   * @param span
-   */
-  public void receiveSpan(Span span);
-
-}


[3/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/htrace/protobuf/generated/SpanProtos.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/htrace/protobuf/generated/SpanProtos.java b/htrace-hbase/src/main/java/org/htrace/protobuf/generated/SpanProtos.java
deleted file mode 100644
index 91f952c..0000000
--- a/htrace-hbase/src/main/java/org/htrace/protobuf/generated/SpanProtos.java
+++ /dev/null
@@ -1,2241 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: Span.proto
-
-package org.htrace.protobuf.generated;
-
-public final class SpanProtos {
-  private SpanProtos() {}
-  public static void registerAllExtensions(
-      com.google.protobuf.ExtensionRegistry registry) {
-  }
-  public interface TimelineAnnotationOrBuilder
-      extends com.google.protobuf.MessageOrBuilder {
-
-    // required int64 time = 1;
-    /**
-     * <code>required int64 time = 1;</code>
-     */
-    boolean hasTime();
-    /**
-     * <code>required int64 time = 1;</code>
-     */
-    long getTime();
-
-    // required string message = 2;
-    /**
-     * <code>required string message = 2;</code>
-     */
-    boolean hasMessage();
-    /**
-     * <code>required string message = 2;</code>
-     */
-    java.lang.String getMessage();
-    /**
-     * <code>required string message = 2;</code>
-     */
-    com.google.protobuf.ByteString
-        getMessageBytes();
-  }
-  /**
-   * Protobuf type {@code TimelineAnnotation}
-   */
-  public static final class TimelineAnnotation extends
-      com.google.protobuf.GeneratedMessage
-      implements TimelineAnnotationOrBuilder {
-    // Use TimelineAnnotation.newBuilder() to construct.
-    private TimelineAnnotation(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-      super(builder);
-      this.unknownFields = builder.getUnknownFields();
-    }
-    private TimelineAnnotation(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
-    private static final TimelineAnnotation defaultInstance;
-    public static TimelineAnnotation getDefaultInstance() {
-      return defaultInstance;
-    }
-
-    public TimelineAnnotation getDefaultInstanceForType() {
-      return defaultInstance;
-    }
-
-    private final com.google.protobuf.UnknownFieldSet unknownFields;
-    @java.lang.Override
-    public final com.google.protobuf.UnknownFieldSet
-        getUnknownFields() {
-      return this.unknownFields;
-    }
-    private TimelineAnnotation(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      initFields();
-      int mutable_bitField0_ = 0;
-      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
-          com.google.protobuf.UnknownFieldSet.newBuilder();
-      try {
-        boolean done = false;
-        while (!done) {
-          int tag = input.readTag();
-          switch (tag) {
-            case 0:
-              done = true;
-              break;
-            default: {
-              if (!parseUnknownField(input, unknownFields,
-                                     extensionRegistry, tag)) {
-                done = true;
-              }
-              break;
-            }
-            case 8: {
-              bitField0_ |= 0x00000001;
-              time_ = input.readInt64();
-              break;
-            }
-            case 18: {
-              bitField0_ |= 0x00000002;
-              message_ = input.readBytes();
-              break;
-            }
-          }
-        }
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.setUnfinishedMessage(this);
-      } catch (java.io.IOException e) {
-        throw new com.google.protobuf.InvalidProtocolBufferException(
-            e.getMessage()).setUnfinishedMessage(this);
-      } finally {
-        this.unknownFields = unknownFields.build();
-        makeExtensionsImmutable();
-      }
-    }
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return org.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_descriptor;
-    }
-
-    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return org.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.class, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder.class);
-    }
-
-    public static com.google.protobuf.Parser<TimelineAnnotation> PARSER =
-        new com.google.protobuf.AbstractParser<TimelineAnnotation>() {
-      public TimelineAnnotation parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return new TimelineAnnotation(input, extensionRegistry);
-      }
-    };
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<TimelineAnnotation> getParserForType() {
-      return PARSER;
-    }
-
-    private int bitField0_;
-    // required int64 time = 1;
-    public static final int TIME_FIELD_NUMBER = 1;
-    private long time_;
-    /**
-     * <code>required int64 time = 1;</code>
-     */
-    public boolean hasTime() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>required int64 time = 1;</code>
-     */
-    public long getTime() {
-      return time_;
-    }
-
-    // required string message = 2;
-    public static final int MESSAGE_FIELD_NUMBER = 2;
-    private java.lang.Object message_;
-    /**
-     * <code>required string message = 2;</code>
-     */
-    public boolean hasMessage() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
-    }
-    /**
-     * <code>required string message = 2;</code>
-     */
-    public java.lang.String getMessage() {
-      java.lang.Object ref = message_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        if (bs.isValidUtf8()) {
-          message_ = s;
-        }
-        return s;
-      }
-    }
-    /**
-     * <code>required string message = 2;</code>
-     */
-    public com.google.protobuf.ByteString
-        getMessageBytes() {
-      java.lang.Object ref = message_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        message_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    private void initFields() {
-      time_ = 0L;
-      message_ = "";
-    }
-    private byte memoizedIsInitialized = -1;
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized != -1) return isInitialized == 1;
-
-      if (!hasTime()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasMessage()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeInt64(1, time_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeBytes(2, getMessageBytes());
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    private int memoizedSerializedSize = -1;
-    public int getSerializedSize() {
-      int size = memoizedSerializedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(1, time_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(2, getMessageBytes());
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSerializedSize = size;
-      return size;
-    }
-
-    private static final long serialVersionUID = 0L;
-    @java.lang.Override
-    protected java.lang.Object writeReplace()
-        throws java.io.ObjectStreamException {
-      return super.writeReplace();
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation)) {
-        return super.equals(obj);
-      }
-      org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation other = (org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation) obj;
-
-      boolean result = true;
-      result = result && (hasTime() == other.hasTime());
-      if (hasTime()) {
-        result = result && (getTime()
-            == other.getTime());
-      }
-      result = result && (hasMessage() == other.hasMessage());
-      if (hasMessage()) {
-        result = result && getMessage()
-            .equals(other.getMessage());
-      }
-      result = result &&
-          getUnknownFields().equals(other.getUnknownFields());
-      return result;
-    }
-
-    private int memoizedHashCode = 0;
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptorForType().hashCode();
-      if (hasTime()) {
-        hash = (37 * hash) + TIME_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getTime());
-      }
-      if (hasMessage()) {
-        hash = (37 * hash) + MESSAGE_FIELD_NUMBER;
-        hash = (53 * hash) + getMessage().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-
-    public static Builder newBuilder() { return Builder.create(); }
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation prototype) {
-      return newBuilder().mergeFrom(prototype);
-    }
-    public Builder toBuilder() { return newBuilder(this); }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * Protobuf type {@code TimelineAnnotation}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessage.Builder<Builder>
-       implements org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return org.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_descriptor;
-      }
-
-      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return org.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.class, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder.class);
-      }
-
-      // Construct using org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.newBuilder()
-      private Builder() {
-        maybeForceBuilderInitialization();
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-        super(parent);
-        maybeForceBuilderInitialization();
-      }
-      private void maybeForceBuilderInitialization() {
-        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-        }
-      }
-      private static Builder create() {
-        return new Builder();
-      }
-
-      public Builder clear() {
-        super.clear();
-        time_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000001);
-        message_ = "";
-        bitField0_ = (bitField0_ & ~0x00000002);
-        return this;
-      }
-
-      public Builder clone() {
-        return create().mergeFrom(buildPartial());
-      }
-
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return org.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_descriptor;
-      }
-
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getDefaultInstanceForType() {
-        return org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance();
-      }
-
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation build() {
-        org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation buildPartial() {
-        org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation result = new org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation(this);
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-          to_bitField0_ |= 0x00000001;
-        }
-        result.time_ = time_;
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.message_ = message_;
-        result.bitField0_ = to_bitField0_;
-        onBuilt();
-        return result;
-      }
-
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation) {
-          return mergeFrom((org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation other) {
-        if (other == org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance()) return this;
-        if (other.hasTime()) {
-          setTime(other.getTime());
-        }
-        if (other.hasMessage()) {
-          bitField0_ |= 0x00000002;
-          message_ = other.message_;
-          onChanged();
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        return this;
-      }
-
-      public final boolean isInitialized() {
-        if (!hasTime()) {
-          
-          return false;
-        }
-        if (!hasMessage()) {
-          
-          return false;
-        }
-        return true;
-      }
-
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parsedMessage = null;
-        try {
-          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation) e.getUnfinishedMessage();
-          throw e;
-        } finally {
-          if (parsedMessage != null) {
-            mergeFrom(parsedMessage);
-          }
-        }
-        return this;
-      }
-      private int bitField0_;
-
-      // required int64 time = 1;
-      private long time_ ;
-      /**
-       * <code>required int64 time = 1;</code>
-       */
-      public boolean hasTime() {
-        return ((bitField0_ & 0x00000001) == 0x00000001);
-      }
-      /**
-       * <code>required int64 time = 1;</code>
-       */
-      public long getTime() {
-        return time_;
-      }
-      /**
-       * <code>required int64 time = 1;</code>
-       */
-      public Builder setTime(long value) {
-        bitField0_ |= 0x00000001;
-        time_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 time = 1;</code>
-       */
-      public Builder clearTime() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        time_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // required string message = 2;
-      private java.lang.Object message_ = "";
-      /**
-       * <code>required string message = 2;</code>
-       */
-      public boolean hasMessage() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
-      }
-      /**
-       * <code>required string message = 2;</code>
-       */
-      public java.lang.String getMessage() {
-        java.lang.Object ref = message_;
-        if (!(ref instanceof java.lang.String)) {
-          java.lang.String s = ((com.google.protobuf.ByteString) ref)
-              .toStringUtf8();
-          message_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <code>required string message = 2;</code>
-       */
-      public com.google.protobuf.ByteString
-          getMessageBytes() {
-        java.lang.Object ref = message_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          message_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <code>required string message = 2;</code>
-       */
-      public Builder setMessage(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000002;
-        message_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string message = 2;</code>
-       */
-      public Builder clearMessage() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        message_ = getDefaultInstance().getMessage();
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string message = 2;</code>
-       */
-      public Builder setMessageBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000002;
-        message_ = value;
-        onChanged();
-        return this;
-      }
-
-      // @@protoc_insertion_point(builder_scope:TimelineAnnotation)
-    }
-
-    static {
-      defaultInstance = new TimelineAnnotation(true);
-      defaultInstance.initFields();
-    }
-
-    // @@protoc_insertion_point(class_scope:TimelineAnnotation)
-  }
-
-  public interface SpanOrBuilder
-      extends com.google.protobuf.MessageOrBuilder {
-
-    // required int64 trace_id = 1;
-    /**
-     * <code>required int64 trace_id = 1;</code>
-     */
-    boolean hasTraceId();
-    /**
-     * <code>required int64 trace_id = 1;</code>
-     */
-    long getTraceId();
-
-    // required int64 parent_id = 2;
-    /**
-     * <code>required int64 parent_id = 2;</code>
-     */
-    boolean hasParentId();
-    /**
-     * <code>required int64 parent_id = 2;</code>
-     */
-    long getParentId();
-
-    // required int64 start = 3;
-    /**
-     * <code>required int64 start = 3;</code>
-     */
-    boolean hasStart();
-    /**
-     * <code>required int64 start = 3;</code>
-     */
-    long getStart();
-
-    // required int64 stop = 4;
-    /**
-     * <code>required int64 stop = 4;</code>
-     */
-    boolean hasStop();
-    /**
-     * <code>required int64 stop = 4;</code>
-     */
-    long getStop();
-
-    // required int64 span_id = 5;
-    /**
-     * <code>required int64 span_id = 5;</code>
-     */
-    boolean hasSpanId();
-    /**
-     * <code>required int64 span_id = 5;</code>
-     */
-    long getSpanId();
-
-    // required string process_id = 6;
-    /**
-     * <code>required string process_id = 6;</code>
-     */
-    boolean hasProcessId();
-    /**
-     * <code>required string process_id = 6;</code>
-     */
-    java.lang.String getProcessId();
-    /**
-     * <code>required string process_id = 6;</code>
-     */
-    com.google.protobuf.ByteString
-        getProcessIdBytes();
-
-    // required string description = 7;
-    /**
-     * <code>required string description = 7;</code>
-     */
-    boolean hasDescription();
-    /**
-     * <code>required string description = 7;</code>
-     */
-    java.lang.String getDescription();
-    /**
-     * <code>required string description = 7;</code>
-     */
-    com.google.protobuf.ByteString
-        getDescriptionBytes();
-
-    // repeated .TimelineAnnotation timeline = 8;
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    java.util.List<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> 
-        getTimelineList();
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getTimeline(int index);
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    int getTimelineCount();
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    java.util.List<? extends org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
-        getTimelineOrBuilderList();
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder getTimelineOrBuilder(
-        int index);
-  }
-  /**
-   * Protobuf type {@code Span}
-   */
-  public static final class Span extends
-      com.google.protobuf.GeneratedMessage
-      implements SpanOrBuilder {
-    // Use Span.newBuilder() to construct.
-    private Span(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-      super(builder);
-      this.unknownFields = builder.getUnknownFields();
-    }
-    private Span(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
-    private static final Span defaultInstance;
-    public static Span getDefaultInstance() {
-      return defaultInstance;
-    }
-
-    public Span getDefaultInstanceForType() {
-      return defaultInstance;
-    }
-
-    private final com.google.protobuf.UnknownFieldSet unknownFields;
-    @java.lang.Override
-    public final com.google.protobuf.UnknownFieldSet
-        getUnknownFields() {
-      return this.unknownFields;
-    }
-    private Span(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      initFields();
-      int mutable_bitField0_ = 0;
-      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
-          com.google.protobuf.UnknownFieldSet.newBuilder();
-      try {
-        boolean done = false;
-        while (!done) {
-          int tag = input.readTag();
-          switch (tag) {
-            case 0:
-              done = true;
-              break;
-            default: {
-              if (!parseUnknownField(input, unknownFields,
-                                     extensionRegistry, tag)) {
-                done = true;
-              }
-              break;
-            }
-            case 8: {
-              bitField0_ |= 0x00000001;
-              traceId_ = input.readInt64();
-              break;
-            }
-            case 16: {
-              bitField0_ |= 0x00000002;
-              parentId_ = input.readInt64();
-              break;
-            }
-            case 24: {
-              bitField0_ |= 0x00000004;
-              start_ = input.readInt64();
-              break;
-            }
-            case 32: {
-              bitField0_ |= 0x00000008;
-              stop_ = input.readInt64();
-              break;
-            }
-            case 40: {
-              bitField0_ |= 0x00000010;
-              spanId_ = input.readInt64();
-              break;
-            }
-            case 50: {
-              bitField0_ |= 0x00000020;
-              processId_ = input.readBytes();
-              break;
-            }
-            case 58: {
-              bitField0_ |= 0x00000040;
-              description_ = input.readBytes();
-              break;
-            }
-            case 66: {
-              if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
-                timeline_ = new java.util.ArrayList<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation>();
-                mutable_bitField0_ |= 0x00000080;
-              }
-              timeline_.add(input.readMessage(org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.PARSER, extensionRegistry));
-              break;
-            }
-          }
-        }
-      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-        throw e.setUnfinishedMessage(this);
-      } catch (java.io.IOException e) {
-        throw new com.google.protobuf.InvalidProtocolBufferException(
-            e.getMessage()).setUnfinishedMessage(this);
-      } finally {
-        if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
-          timeline_ = java.util.Collections.unmodifiableList(timeline_);
-        }
-        this.unknownFields = unknownFields.build();
-        makeExtensionsImmutable();
-      }
-    }
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return org.htrace.protobuf.generated.SpanProtos.internal_static_Span_descriptor;
-    }
-
-    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return org.htrace.protobuf.generated.SpanProtos.internal_static_Span_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              org.htrace.protobuf.generated.SpanProtos.Span.class, org.htrace.protobuf.generated.SpanProtos.Span.Builder.class);
-    }
-
-    public static com.google.protobuf.Parser<Span> PARSER =
-        new com.google.protobuf.AbstractParser<Span>() {
-      public Span parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return new Span(input, extensionRegistry);
-      }
-    };
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<Span> getParserForType() {
-      return PARSER;
-    }
-
-    private int bitField0_;
-    // required int64 trace_id = 1;
-    public static final int TRACE_ID_FIELD_NUMBER = 1;
-    private long traceId_;
-    /**
-     * <code>required int64 trace_id = 1;</code>
-     */
-    public boolean hasTraceId() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>required int64 trace_id = 1;</code>
-     */
-    public long getTraceId() {
-      return traceId_;
-    }
-
-    // required int64 parent_id = 2;
-    public static final int PARENT_ID_FIELD_NUMBER = 2;
-    private long parentId_;
-    /**
-     * <code>required int64 parent_id = 2;</code>
-     */
-    public boolean hasParentId() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
-    }
-    /**
-     * <code>required int64 parent_id = 2;</code>
-     */
-    public long getParentId() {
-      return parentId_;
-    }
-
-    // required int64 start = 3;
-    public static final int START_FIELD_NUMBER = 3;
-    private long start_;
-    /**
-     * <code>required int64 start = 3;</code>
-     */
-    public boolean hasStart() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
-    }
-    /**
-     * <code>required int64 start = 3;</code>
-     */
-    public long getStart() {
-      return start_;
-    }
-
-    // required int64 stop = 4;
-    public static final int STOP_FIELD_NUMBER = 4;
-    private long stop_;
-    /**
-     * <code>required int64 stop = 4;</code>
-     */
-    public boolean hasStop() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>required int64 stop = 4;</code>
-     */
-    public long getStop() {
-      return stop_;
-    }
-
-    // required int64 span_id = 5;
-    public static final int SPAN_ID_FIELD_NUMBER = 5;
-    private long spanId_;
-    /**
-     * <code>required int64 span_id = 5;</code>
-     */
-    public boolean hasSpanId() {
-      return ((bitField0_ & 0x00000010) == 0x00000010);
-    }
-    /**
-     * <code>required int64 span_id = 5;</code>
-     */
-    public long getSpanId() {
-      return spanId_;
-    }
-
-    // required string process_id = 6;
-    public static final int PROCESS_ID_FIELD_NUMBER = 6;
-    private java.lang.Object processId_;
-    /**
-     * <code>required string process_id = 6;</code>
-     */
-    public boolean hasProcessId() {
-      return ((bitField0_ & 0x00000020) == 0x00000020);
-    }
-    /**
-     * <code>required string process_id = 6;</code>
-     */
-    public java.lang.String getProcessId() {
-      java.lang.Object ref = processId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        if (bs.isValidUtf8()) {
-          processId_ = s;
-        }
-        return s;
-      }
-    }
-    /**
-     * <code>required string process_id = 6;</code>
-     */
-    public com.google.protobuf.ByteString
-        getProcessIdBytes() {
-      java.lang.Object ref = processId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        processId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    // required string description = 7;
-    public static final int DESCRIPTION_FIELD_NUMBER = 7;
-    private java.lang.Object description_;
-    /**
-     * <code>required string description = 7;</code>
-     */
-    public boolean hasDescription() {
-      return ((bitField0_ & 0x00000040) == 0x00000040);
-    }
-    /**
-     * <code>required string description = 7;</code>
-     */
-    public java.lang.String getDescription() {
-      java.lang.Object ref = description_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        if (bs.isValidUtf8()) {
-          description_ = s;
-        }
-        return s;
-      }
-    }
-    /**
-     * <code>required string description = 7;</code>
-     */
-    public com.google.protobuf.ByteString
-        getDescriptionBytes() {
-      java.lang.Object ref = description_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        description_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
-    }
-
-    // repeated .TimelineAnnotation timeline = 8;
-    public static final int TIMELINE_FIELD_NUMBER = 8;
-    private java.util.List<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> timeline_;
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    public java.util.List<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> getTimelineList() {
-      return timeline_;
-    }
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    public java.util.List<? extends org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
-        getTimelineOrBuilderList() {
-      return timeline_;
-    }
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    public int getTimelineCount() {
-      return timeline_.size();
-    }
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getTimeline(int index) {
-      return timeline_.get(index);
-    }
-    /**
-     * <code>repeated .TimelineAnnotation timeline = 8;</code>
-     */
-    public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder getTimelineOrBuilder(
-        int index) {
-      return timeline_.get(index);
-    }
-
-    private void initFields() {
-      traceId_ = 0L;
-      parentId_ = 0L;
-      start_ = 0L;
-      stop_ = 0L;
-      spanId_ = 0L;
-      processId_ = "";
-      description_ = "";
-      timeline_ = java.util.Collections.emptyList();
-    }
-    private byte memoizedIsInitialized = -1;
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized != -1) return isInitialized == 1;
-
-      if (!hasTraceId()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasParentId()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasStart()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasStop()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasSpanId()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasProcessId()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasDescription()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      for (int i = 0; i < getTimelineCount(); i++) {
-        if (!getTimeline(i).isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeInt64(1, traceId_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeInt64(2, parentId_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeInt64(3, start_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeInt64(4, stop_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        output.writeInt64(5, spanId_);
-      }
-      if (((bitField0_ & 0x00000020) == 0x00000020)) {
-        output.writeBytes(6, getProcessIdBytes());
-      }
-      if (((bitField0_ & 0x00000040) == 0x00000040)) {
-        output.writeBytes(7, getDescriptionBytes());
-      }
-      for (int i = 0; i < timeline_.size(); i++) {
-        output.writeMessage(8, timeline_.get(i));
-      }
-      getUnknownFields().writeTo(output);
-    }
-
-    private int memoizedSerializedSize = -1;
-    public int getSerializedSize() {
-      int size = memoizedSerializedSize;
-      if (size != -1) return size;
-
-      size = 0;
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(1, traceId_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(2, parentId_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(3, start_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(4, stop_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(5, spanId_);
-      }
-      if (((bitField0_ & 0x00000020) == 0x00000020)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(6, getProcessIdBytes());
-      }
-      if (((bitField0_ & 0x00000040) == 0x00000040)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(7, getDescriptionBytes());
-      }
-      for (int i = 0; i < timeline_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(8, timeline_.get(i));
-      }
-      size += getUnknownFields().getSerializedSize();
-      memoizedSerializedSize = size;
-      return size;
-    }
-
-    private static final long serialVersionUID = 0L;
-    @java.lang.Override
-    protected java.lang.Object writeReplace()
-        throws java.io.ObjectStreamException {
-      return super.writeReplace();
-    }
-
-    @java.lang.Override
-    public boolean equals(final java.lang.Object obj) {
-      if (obj == this) {
-       return true;
-      }
-      if (!(obj instanceof org.htrace.protobuf.generated.SpanProtos.Span)) {
-        return super.equals(obj);
-      }
-      org.htrace.protobuf.generated.SpanProtos.Span other = (org.htrace.protobuf.generated.SpanProtos.Span) obj;
-
-      boolean result = true;
-      result = result && (hasTraceId() == other.hasTraceId());
-      if (hasTraceId()) {
-        result = result && (getTraceId()
-            == other.getTraceId());
-      }
-      result = result && (hasParentId() == other.hasParentId());
-      if (hasParentId()) {
-        result = result && (getParentId()
-            == other.getParentId());
-      }
-      result = result && (hasStart() == other.hasStart());
-      if (hasStart()) {
-        result = result && (getStart()
-            == other.getStart());
-      }
-      result = result && (hasStop() == other.hasStop());
-      if (hasStop()) {
-        result = result && (getStop()
-            == other.getStop());
-      }
-      result = result && (hasSpanId() == other.hasSpanId());
-      if (hasSpanId()) {
-        result = result && (getSpanId()
-            == other.getSpanId());
-      }
-      result = result && (hasProcessId() == other.hasProcessId());
-      if (hasProcessId()) {
-        result = result && getProcessId()
-            .equals(other.getProcessId());
-      }
-      result = result && (hasDescription() == other.hasDescription());
-      if (hasDescription()) {
-        result = result && getDescription()
-            .equals(other.getDescription());
-      }
-      result = result && getTimelineList()
-          .equals(other.getTimelineList());
-      result = result &&
-          getUnknownFields().equals(other.getUnknownFields());
-      return result;
-    }
-
-    private int memoizedHashCode = 0;
-    @java.lang.Override
-    public int hashCode() {
-      if (memoizedHashCode != 0) {
-        return memoizedHashCode;
-      }
-      int hash = 41;
-      hash = (19 * hash) + getDescriptorForType().hashCode();
-      if (hasTraceId()) {
-        hash = (37 * hash) + TRACE_ID_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getTraceId());
-      }
-      if (hasParentId()) {
-        hash = (37 * hash) + PARENT_ID_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getParentId());
-      }
-      if (hasStart()) {
-        hash = (37 * hash) + START_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getStart());
-      }
-      if (hasStop()) {
-        hash = (37 * hash) + STOP_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getStop());
-      }
-      if (hasSpanId()) {
-        hash = (37 * hash) + SPAN_ID_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getSpanId());
-      }
-      if (hasProcessId()) {
-        hash = (37 * hash) + PROCESS_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getProcessId().hashCode();
-      }
-      if (hasDescription()) {
-        hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER;
-        hash = (53 * hash) + getDescription().hashCode();
-      }
-      if (getTimelineCount() > 0) {
-        hash = (37 * hash) + TIMELINE_FIELD_NUMBER;
-        hash = (53 * hash) + getTimelineList().hashCode();
-      }
-      hash = (29 * hash) + getUnknownFields().hashCode();
-      memoizedHashCode = hash;
-      return hash;
-    }
-
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input, extensionRegistry);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(
-        com.google.protobuf.CodedInputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.htrace.protobuf.generated.SpanProtos.Span parseFrom(
-        com.google.protobuf.CodedInputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-
-    public static Builder newBuilder() { return Builder.create(); }
-    public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.htrace.protobuf.generated.SpanProtos.Span prototype) {
-      return newBuilder().mergeFrom(prototype);
-    }
-    public Builder toBuilder() { return newBuilder(this); }
-
-    @java.lang.Override
-    protected Builder newBuilderForType(
-        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-      Builder builder = new Builder(parent);
-      return builder;
-    }
-    /**
-     * Protobuf type {@code Span}
-     */
-    public static final class Builder extends
-        com.google.protobuf.GeneratedMessage.Builder<Builder>
-       implements org.htrace.protobuf.generated.SpanProtos.SpanOrBuilder {
-      public static final com.google.protobuf.Descriptors.Descriptor
-          getDescriptor() {
-        return org.htrace.protobuf.generated.SpanProtos.internal_static_Span_descriptor;
-      }
-
-      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-          internalGetFieldAccessorTable() {
-        return org.htrace.protobuf.generated.SpanProtos.internal_static_Span_fieldAccessorTable
-            .ensureFieldAccessorsInitialized(
-                org.htrace.protobuf.generated.SpanProtos.Span.class, org.htrace.protobuf.generated.SpanProtos.Span.Builder.class);
-      }
-
-      // Construct using org.htrace.protobuf.generated.SpanProtos.Span.newBuilder()
-      private Builder() {
-        maybeForceBuilderInitialization();
-      }
-
-      private Builder(
-          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-        super(parent);
-        maybeForceBuilderInitialization();
-      }
-      private void maybeForceBuilderInitialization() {
-        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-          getTimelineFieldBuilder();
-        }
-      }
-      private static Builder create() {
-        return new Builder();
-      }
-
-      public Builder clear() {
-        super.clear();
-        traceId_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000001);
-        parentId_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000002);
-        start_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000004);
-        stop_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000008);
-        spanId_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000010);
-        processId_ = "";
-        bitField0_ = (bitField0_ & ~0x00000020);
-        description_ = "";
-        bitField0_ = (bitField0_ & ~0x00000040);
-        if (timelineBuilder_ == null) {
-          timeline_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000080);
-        } else {
-          timelineBuilder_.clear();
-        }
-        return this;
-      }
-
-      public Builder clone() {
-        return create().mergeFrom(buildPartial());
-      }
-
-      public com.google.protobuf.Descriptors.Descriptor
-          getDescriptorForType() {
-        return org.htrace.protobuf.generated.SpanProtos.internal_static_Span_descriptor;
-      }
-
-      public org.htrace.protobuf.generated.SpanProtos.Span getDefaultInstanceForType() {
-        return org.htrace.protobuf.generated.SpanProtos.Span.getDefaultInstance();
-      }
-
-      public org.htrace.protobuf.generated.SpanProtos.Span build() {
-        org.htrace.protobuf.generated.SpanProtos.Span result = buildPartial();
-        if (!result.isInitialized()) {
-          throw newUninitializedMessageException(result);
-        }
-        return result;
-      }
-
-      public org.htrace.protobuf.generated.SpanProtos.Span buildPartial() {
-        org.htrace.protobuf.generated.SpanProtos.Span result = new org.htrace.protobuf.generated.SpanProtos.Span(this);
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-          to_bitField0_ |= 0x00000001;
-        }
-        result.traceId_ = traceId_;
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.parentId_ = parentId_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        result.start_ = start_;
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.stop_ = stop_;
-        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
-          to_bitField0_ |= 0x00000010;
-        }
-        result.spanId_ = spanId_;
-        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
-          to_bitField0_ |= 0x00000020;
-        }
-        result.processId_ = processId_;
-        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
-          to_bitField0_ |= 0x00000040;
-        }
-        result.description_ = description_;
-        if (timelineBuilder_ == null) {
-          if (((bitField0_ & 0x00000080) == 0x00000080)) {
-            timeline_ = java.util.Collections.unmodifiableList(timeline_);
-            bitField0_ = (bitField0_ & ~0x00000080);
-          }
-          result.timeline_ = timeline_;
-        } else {
-          result.timeline_ = timelineBuilder_.build();
-        }
-        result.bitField0_ = to_bitField0_;
-        onBuilt();
-        return result;
-      }
-
-      public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.htrace.protobuf.generated.SpanProtos.Span) {
-          return mergeFrom((org.htrace.protobuf.generated.SpanProtos.Span)other);
-        } else {
-          super.mergeFrom(other);
-          return this;
-        }
-      }
-
-      public Builder mergeFrom(org.htrace.protobuf.generated.SpanProtos.Span other) {
-        if (other == org.htrace.protobuf.generated.SpanProtos.Span.getDefaultInstance()) return this;
-        if (other.hasTraceId()) {
-          setTraceId(other.getTraceId());
-        }
-        if (other.hasParentId()) {
-          setParentId(other.getParentId());
-        }
-        if (other.hasStart()) {
-          setStart(other.getStart());
-        }
-        if (other.hasStop()) {
-          setStop(other.getStop());
-        }
-        if (other.hasSpanId()) {
-          setSpanId(other.getSpanId());
-        }
-        if (other.hasProcessId()) {
-          bitField0_ |= 0x00000020;
-          processId_ = other.processId_;
-          onChanged();
-        }
-        if (other.hasDescription()) {
-          bitField0_ |= 0x00000040;
-          description_ = other.description_;
-          onChanged();
-        }
-        if (timelineBuilder_ == null) {
-          if (!other.timeline_.isEmpty()) {
-            if (timeline_.isEmpty()) {
-              timeline_ = other.timeline_;
-              bitField0_ = (bitField0_ & ~0x00000080);
-            } else {
-              ensureTimelineIsMutable();
-              timeline_.addAll(other.timeline_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.timeline_.isEmpty()) {
-            if (timelineBuilder_.isEmpty()) {
-              timelineBuilder_.dispose();
-              timelineBuilder_ = null;
-              timeline_ = other.timeline_;
-              bitField0_ = (bitField0_ & ~0x00000080);
-              timelineBuilder_ = 
-                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
-                   getTimelineFieldBuilder() : null;
-            } else {
-              timelineBuilder_.addAllMessages(other.timeline_);
-            }
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        return this;
-      }
-
-      public final boolean isInitialized() {
-        if (!hasTraceId()) {
-          
-          return false;
-        }
-        if (!hasParentId()) {
-          
-          return false;
-        }
-        if (!hasStart()) {
-          
-          return false;
-        }
-        if (!hasStop()) {
-          
-          return false;
-        }
-        if (!hasSpanId()) {
-          
-          return false;
-        }
-        if (!hasProcessId()) {
-          
-          return false;
-        }
-        if (!hasDescription()) {
-          
-          return false;
-        }
-        for (int i = 0; i < getTimelineCount(); i++) {
-          if (!getTimeline(i).isInitialized()) {
-            
-            return false;
-          }
-        }
-        return true;
-      }
-
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        org.htrace.protobuf.generated.SpanProtos.Span parsedMessage = null;
-        try {
-          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.htrace.protobuf.generated.SpanProtos.Span) e.getUnfinishedMessage();
-          throw e;
-        } finally {
-          if (parsedMessage != null) {
-            mergeFrom(parsedMessage);
-          }
-        }
-        return this;
-      }
-      private int bitField0_;
-
-      // required int64 trace_id = 1;
-      private long traceId_ ;
-      /**
-       * <code>required int64 trace_id = 1;</code>
-       */
-      public boolean hasTraceId() {
-        return ((bitField0_ & 0x00000001) == 0x00000001);
-      }
-      /**
-       * <code>required int64 trace_id = 1;</code>
-       */
-      public long getTraceId() {
-        return traceId_;
-      }
-      /**
-       * <code>required int64 trace_id = 1;</code>
-       */
-      public Builder setTraceId(long value) {
-        bitField0_ |= 0x00000001;
-        traceId_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 trace_id = 1;</code>
-       */
-      public Builder clearTraceId() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        traceId_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // required int64 parent_id = 2;
-      private long parentId_ ;
-      /**
-       * <code>required int64 parent_id = 2;</code>
-       */
-      public boolean hasParentId() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
-      }
-      /**
-       * <code>required int64 parent_id = 2;</code>
-       */
-      public long getParentId() {
-        return parentId_;
-      }
-      /**
-       * <code>required int64 parent_id = 2;</code>
-       */
-      public Builder setParentId(long value) {
-        bitField0_ |= 0x00000002;
-        parentId_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 parent_id = 2;</code>
-       */
-      public Builder clearParentId() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        parentId_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // required int64 start = 3;
-      private long start_ ;
-      /**
-       * <code>required int64 start = 3;</code>
-       */
-      public boolean hasStart() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
-      }
-      /**
-       * <code>required int64 start = 3;</code>
-       */
-      public long getStart() {
-        return start_;
-      }
-      /**
-       * <code>required int64 start = 3;</code>
-       */
-      public Builder setStart(long value) {
-        bitField0_ |= 0x00000004;
-        start_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 start = 3;</code>
-       */
-      public Builder clearStart() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        start_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // required int64 stop = 4;
-      private long stop_ ;
-      /**
-       * <code>required int64 stop = 4;</code>
-       */
-      public boolean hasStop() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
-      }
-      /**
-       * <code>required int64 stop = 4;</code>
-       */
-      public long getStop() {
-        return stop_;
-      }
-      /**
-       * <code>required int64 stop = 4;</code>
-       */
-      public Builder setStop(long value) {
-        bitField0_ |= 0x00000008;
-        stop_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 stop = 4;</code>
-       */
-      public Builder clearStop() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        stop_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // required int64 span_id = 5;
-      private long spanId_ ;
-      /**
-       * <code>required int64 span_id = 5;</code>
-       */
-      public boolean hasSpanId() {
-        return ((bitField0_ & 0x00000010) == 0x00000010);
-      }
-      /**
-       * <code>required int64 span_id = 5;</code>
-       */
-      public long getSpanId() {
-        return spanId_;
-      }
-      /**
-       * <code>required int64 span_id = 5;</code>
-       */
-      public Builder setSpanId(long value) {
-        bitField0_ |= 0x00000010;
-        spanId_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 span_id = 5;</code>
-       */
-      public Builder clearSpanId() {
-        bitField0_ = (bitField0_ & ~0x00000010);
-        spanId_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // required string process_id = 6;
-      private java.lang.Object processId_ = "";
-      /**
-       * <code>required string process_id = 6;</code>
-       */
-      public boolean hasProcessId() {
-        return ((bitField0_ & 0x00000020) == 0x00000020);
-      }
-      /**
-       * <code>required string process_id = 6;</code>
-       */
-      public java.lang.String getProcessId() {
-        java.lang.Object ref = processId_;
-        if (!(ref instanceof java.lang.String)) {
-          java.lang.String s = ((com.google.protobuf.ByteString) ref)
-              .toStringUtf8();
-          processId_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <code>required string process_id = 6;</code>
-       */
-      public com.google.protobuf.ByteString
-          getProcessIdBytes() {
-        java.lang.Object ref = processId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          processId_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <code>required string process_id = 6;</code>
-       */
-      public Builder setProcessId(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000020;
-        processId_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string process_id = 6;</code>
-       */
-      public Builder clearProcessId() {
-        bitField0_ = (bitField0_ & ~0x00000020);
-        processId_ = getDefaultInstance().getProcessId();
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string process_id = 6;</code>
-       */
-      public Builder setProcessIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000020;
-        processId_ = value;
-        onChanged();
-        return this;
-      }
-
-      // required string description = 7;
-      private java.lang.Object description_ = "";
-      /**
-       * <code>required string description = 7;</code>
-       */
-      public boolean hasDescription() {
-        return ((bitField0_ & 0x00000040) == 0x00000040);
-      }
-      /**
-       * <code>required string description = 7;</code>
-       */
-      public java.lang.String getDescription() {
-        java.lang.Object ref = description_;
-        if (!(ref instanceof java.lang.String)) {
-          java.lang.String s = ((com.google.protobuf.ByteString) ref)
-              .toStringUtf8();
-          description_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <code>required string description = 7;</code>
-       */
-      public com.google.protobuf.ByteString
-          getDescriptionBytes() {
-        java.lang.Object ref = description_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          description_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <code>required string description = 7;</code>
-       */
-      public Builder setDescription(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000040;
-        description_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string description = 7;</code>
-       */
-      public Builder clearDescription() {
-        bitField0_ = (bitField0_ & ~0x00000040);
-        description_ = getDefaultInstance().getDescription();
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string description = 7;</code>
-       */
-      public Builder setDescriptionBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000040;
-        description_ = value;
-        onChanged();
-        return this;
-      }
-
-      // repeated .TimelineAnnotation timeline = 8;
-      private java.util.List<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> timeline_ =
-        java.util.Collections.emptyList();
-      private void ensureTimelineIsMutable() {
-        if (!((bitField0_ & 0x00000080) == 0x00000080)) {
-          timeline_ = new java.util.ArrayList<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation>(timeline_);
-          bitField0_ |= 0x00000080;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilder<
-          org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> timelineBuilder_;
-
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public java.util.List<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> getTimelineList() {
-        if (timelineBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(timeline_);
-        } else {
-          return timelineBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public int getTimelineCount() {
-        if (timelineBuilder_ == null) {
-          return timeline_.size();
-        } else {
-          return timelineBuilder_.getCount();
-        }
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getTimeline(int index) {
-        if (timelineBuilder_ == null) {
-          return timeline_.get(index);
-        } else {
-          return timelineBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder setTimeline(
-          int index, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation value) {
-        if (timelineBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTimelineIsMutable();
-          timeline_.set(index, value);
-          onChanged();
-        } else {
-          timelineBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder setTimeline(
-          int index, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder builderForValue) {
-        if (timelineBuilder_ == null) {
-          ensureTimelineIsMutable();
-          timeline_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          timelineBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder addTimeline(org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation value) {
-        if (timelineBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTimelineIsMutable();
-          timeline_.add(value);
-          onChanged();
-        } else {
-          timelineBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder addTimeline(
-          int index, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation value) {
-        if (timelineBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTimelineIsMutable();
-          timeline_.add(index, value);
-          onChanged();
-        } else {
-          timelineBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder addTimeline(
-          org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder builderForValue) {
-        if (timelineBuilder_ == null) {
-          ensureTimelineIsMutable();
-          timeline_.add(builderForValue.build());
-          onChanged();
-        } else {
-          timelineBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder addTimeline(
-          int index, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder builderForValue) {
-        if (timelineBuilder_ == null) {
-          ensureTimelineIsMutable();
-          timeline_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          timelineBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder addAllTimeline(
-          java.lang.Iterable<? extends org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> values) {
-        if (timelineBuilder_ == null) {
-          ensureTimelineIsMutable();
-          super.addAll(values, timeline_);
-          onChanged();
-        } else {
-          timelineBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder clearTimeline() {
-        if (timelineBuilder_ == null) {
-          timeline_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000080);
-          onChanged();
-        } else {
-          timelineBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public Builder removeTimeline(int index) {
-        if (timelineBuilder_ == null) {
-          ensureTimelineIsMutable();
-          timeline_.remove(index);
-          onChanged();
-        } else {
-          timelineBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder getTimelineBuilder(
-          int index) {
-        return getTimelineFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder getTimelineOrBuilder(
-          int index) {
-        if (timelineBuilder_ == null) {
-          return timeline_.get(index);  } else {
-          return timelineBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public java.util.List<? extends org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
-           getTimelineOrBuilderList() {
-        if (timelineBuilder_ != null) {
-          return timelineBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(timeline_);
-        }
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder addTimelineBuilder() {
-        return getTimelineFieldBuilder().addBuilder(
-            org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance());
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder addTimelineBuilder(
-          int index) {
-        return getTimelineFieldBuilder().addBuilder(
-            index, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance());
-      }
-      /**
-       * <code>repeated .TimelineAnnotation timeline = 8;</code>
-       */
-      public java.util.List<org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder> 
-           getTimelineBuilderList() {
-        return getTimelineFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilder<
-          org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
-          getTimelineFieldBuilder() {
-        if (timelineBuilder_ == null) {
-          timelineBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder, org.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder>(
-                  timeline_,
-                  ((bitField0_ & 0x00000080) == 0x00000080),
-                  getParentForChildren(),
-                  isClean());
-          timeline_ = null;
-        }
-        return timelineBuilder_;
-      }
-
-      // @@protoc_insertion_point(builder_scope:Span)
-    }
-
-    static {
-      defaultInstance = new Span(true);
-      defaultInstance.initFields();
-    }
-
-    // @@protoc_insertion_point(class_scope:Span)
-  }
-
-  private static com.google.protobuf.Descriptors.Descriptor
-    internal_static_TimelineAnnotation_descriptor;
-  private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-      internal_static_TimelineAnnotation_fieldAccessorTable;
-  private static com.google.protobuf.Descriptors.Descriptor
-    internal_static_Span_descriptor;
-  private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-      internal_static_Span_fieldAccessorTable;
-
-  public static com.google.protobuf.Descriptors.FileDescriptor
-      getDescriptor() {
-    return descriptor;
-  }
-  private static com.google.protobuf.Descriptors.FileDescriptor
-      descriptor;
-  static {
-    java.lang.String[] descriptorData = {
-      "\n\nSpan.proto\"3\n\022TimelineAnnotation\022\014\n\004ti" +
-      "me\030\001 \002(\003\022\017\n\007message\030\002 \002(\t\"\251\001\n\004Span\022\020\n\010tr" +
-      "ace_id\030\001 \002(\003\022\021\n\tparent_id\030\002 \002(\003\022\r\n\005start" +
-      "\030\003 \002(\003\022\014\n\004stop\030\004 \002(\003\022\017\n\007span_id\030\005 \002(\003\022\022\n" +
-      "\nprocess_id\030\006 \002(\t\022\023\n\013description\030\007 \002(\t\022%" +
-      "\n\010timeline\030\010 \003(\0132\023.TimelineAnnotationB0\n" +
-      "\035org.htrace.protobuf.generatedB\nSpanProt" +
-      "osH\001\240\001\001"
-    };
-    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
-      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
-        public com.google.protobuf.ExtensionRegistry assignDescriptors(
-            com.google.protobuf.Descriptors.FileDescriptor root) {
-          descriptor = root;
-          internal_static_TimelineAnnotation_descriptor =
-            getDescriptor().getMessageTypes().get(0);
-          internal_static_TimelineAnnotation_fieldAccessorTable = new
-            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-              internal_static_TimelineAnnotation_descriptor,
-              new java.lang.String[] { "Time", "Message", });
-          internal_static_Span_descriptor =
-            getDescriptor().getMessageTypes().get(1);
-          internal_static_Span_fieldAccessorTable = new
-            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-              internal_static_Span_descriptor,
-              new java.lang.String[] { "TraceId", "ParentId", "Start", "Stop", "SpanId", "ProcessId", "Description", "Timeline", });
-          return null;
-        }
-      };
-    com.google.protobuf.Descriptors.FileDescriptor
-      .internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {
-        }, assigner);
-  }
-
-  // @@protoc_insertion_point(outer_class_scope)
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewer.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewer.java b/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewer.java
deleted file mode 100644
index a22e0c7..0000000
--- a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewer.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.viewer;
-
-import com.google.protobuf.Message;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.Cell;
-import org.apache.hadoop.hbase.CellUtil;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.client.Get;
-import org.apache.hadoop.hbase.client.HConnection;
-import org.apache.hadoop.hbase.client.HConnectionManager;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.htrace.impl.HBaseSpanReceiver;
-import org.htrace.protobuf.generated.SpanProtos;
-
-public class HBaseSpanViewer {
-  private static final Log LOG = LogFactory.getLog(HBaseSpanViewer.class);
-  private Configuration conf;
-  private HConnection hconnection;
-  private HTableInterface htable;
-  private byte[] table;
-  private byte[] cf; 
-  private byte[] icf; 
-
-  public HBaseSpanViewer(Configuration conf) {
-    this.conf = conf;
-    this.table = Bytes.toBytes(conf.get(HBaseSpanReceiver.TABLE_KEY,
-                                        HBaseSpanReceiver.DEFAULT_TABLE));
-    this.cf = Bytes.toBytes(conf.get(HBaseSpanReceiver.COLUMNFAMILY_KEY,
-                                     HBaseSpanReceiver.DEFAULT_COLUMNFAMILY));
-    this.icf = Bytes.toBytes(conf.get(HBaseSpanReceiver.INDEXFAMILY_KEY,
-                                      HBaseSpanReceiver.DEFAULT_INDEXFAMILY));
-  }
-
-  public void close() {
-    stopClient();
-  }
-
-  public void startClient() {
-    if (this.htable == null) {
-      try {
-        this.hconnection = HConnectionManager.createConnection(conf);
-        this.htable = hconnection.getTable(table);
-      } catch (IOException e) {
-        LOG.warn("Failed to create HBase connection. " + e.getMessage());
-      }
-    }
-  }
-
-  public void stopClient() {
-    try {
-      if (this.htable != null) {
-        this.htable.close();
-        this.htable = null;
-      }
-      if (this.hconnection != null) {
-        this.hconnection.close();
-        this.hconnection = null;
-      }
-    } catch (IOException e) {
-      LOG.warn("Failed to close HBase connection. " + e.getMessage());
-    }
-  }
-
-  public List<SpanProtos.Span> getSpans(long traceid) throws IOException {
-    startClient();
-    List<SpanProtos.Span> spans = new ArrayList<SpanProtos.Span>();
-    Get get = new Get(Bytes.toBytes(traceid));
-    get.addFamily(this.cf);
-    try {
-      for (Cell cell : htable.get(get).listCells()) {
-        InputStream in = new ByteArrayInputStream(cell.getQualifierArray(),
-                                                  cell.getQualifierOffset(),
-                                                  cell.getQualifierLength());
-        spans.add(SpanProtos.Span.parseFrom(in));
-      }
-    } catch (IOException e) {
-      LOG.warn("Failed to get spans from HBase. " + e.getMessage());
-      stopClient();
-    }
-    return spans;
-  }
-
-  public List<SpanProtos.Span> getRootSpans() throws IOException {
-    startClient();
-    Scan scan = new Scan();
-    scan.addColumn(this.icf, HBaseSpanReceiver.INDEX_SPAN_QUAL);
-    List<SpanProtos.Span> spans = new ArrayList<SpanProtos.Span>();
-    try {
-      ResultScanner scanner = htable.getScanner(scan);
-      Result result = null;
-      while ((result = scanner.next()) != null) {
-        for (Cell cell : result.listCells()) {
-          InputStream in = new ByteArrayInputStream(cell.getValueArray(),
-                                                    cell.getValueOffset(),
-                                                    cell.getValueLength());
-          spans.add(SpanProtos.Span.parseFrom(in));
-        }
-      }
-    } catch (IOException e) {
-      LOG.warn("Failed to get root spans from HBase. " + e.getMessage());
-      stopClient();
-    }
-    return spans;
-  }
-
-  public static String toJsonString(final Message message) throws IOException {
-    ByteArrayOutputStream out = new ByteArrayOutputStream();
-    OutputStreamWriter writer =
-        new OutputStreamWriter(out, Charset.defaultCharset());
-    appendJsonString(message, writer);
-    writer.flush();
-    out.flush();
-    return out.toString();
-  }
-
-  public static void appendJsonString(final Message message,
-                                        OutputStreamWriter writer) throws IOException {
-    writer.append("{");
-    for (Iterator<Map.Entry<FieldDescriptor, Object>> iter =
-           message.getAllFields().entrySet().iterator(); iter.hasNext();) {
-      Map.Entry<FieldDescriptor, Object> field = iter.next();
-      appendFields(field.getKey(), field.getValue(), writer);
-      if (iter.hasNext()) {
-        writer.append(",");
-      }
-    }
-    writer.append("}");
-  }
-  
-
-  private static void appendFields(FieldDescriptor fd,
-                                   Object value, 
-                                   OutputStreamWriter writer) throws IOException {
-    writer.append("\"");
-    writer.append(fd.getName());
-    writer.append("\"");
-    writer.append(":");
-    if (fd.isRepeated()) {
-      writer.append("[");
-      for (Iterator<?> it = ((List<?>) value).iterator(); it.hasNext();) {
-        appendValue(fd, it.next(), writer);
-        if (it.hasNext()) {
-          writer.append(",");
-        }
-      }
-      writer.append("]");
-    } else {
-      appendValue(fd, value, writer);
-    }
-  }
-
-  private static void appendValue(FieldDescriptor fd,
-                                  Object value, 
-                                  OutputStreamWriter writer) throws IOException {
-    switch (fd.getType()) {
-    case INT64: // write int as string for handling in javascript
-    case STRING:
-      writer.append("\"");
-      writer.append(value.toString());
-      writer.append("\"");
-      break;
-    case MESSAGE:
-      appendJsonString((Message)value, writer);
-      break;
-    default:
-      throw new IOException("unexpected field type.");
-    }
-  }
-
-  /**
-   * Run basic test.
-   * @throws IOException
-   */
-  public static void main(String[] args) throws IOException {
-    HBaseSpanViewer viewer = new HBaseSpanViewer(HBaseConfiguration.create());
-    if (args.length == 0) {
-      List<SpanProtos.Span> spans = viewer.getRootSpans();
-      for (SpanProtos.Span span : spans) {
-        System.out.println(toJsonString(span));
-      }
-    } else {
-      List<SpanProtos.Span> spans = viewer.getSpans(Long.parseLong(args[0]));
-      for (SpanProtos.Span span : spans) {
-        System.out.println(toJsonString(span));
-      }
-    }
-    viewer.close();
-  }
-}


[5/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/apache/htrace/protobuf/generated/SpanProtos.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/apache/htrace/protobuf/generated/SpanProtos.java b/htrace-hbase/src/main/java/org/apache/htrace/protobuf/generated/SpanProtos.java
new file mode 100644
index 0000000..98b8adb
--- /dev/null
+++ b/htrace-hbase/src/main/java/org/apache/htrace/protobuf/generated/SpanProtos.java
@@ -0,0 +1,2241 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: Span.proto
+
+package org.apache.htrace.protobuf.generated;
+
+public final class SpanProtos {
+  private SpanProtos() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface TimelineAnnotationOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required int64 time = 1;
+    /**
+     * <code>required int64 time = 1;</code>
+     */
+    boolean hasTime();
+    /**
+     * <code>required int64 time = 1;</code>
+     */
+    long getTime();
+
+    // required string message = 2;
+    /**
+     * <code>required string message = 2;</code>
+     */
+    boolean hasMessage();
+    /**
+     * <code>required string message = 2;</code>
+     */
+    java.lang.String getMessage();
+    /**
+     * <code>required string message = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getMessageBytes();
+  }
+  /**
+   * Protobuf type {@code TimelineAnnotation}
+   */
+  public static final class TimelineAnnotation extends
+      com.google.protobuf.GeneratedMessage
+      implements TimelineAnnotationOrBuilder {
+    // Use TimelineAnnotation.newBuilder() to construct.
+    private TimelineAnnotation(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private TimelineAnnotation(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final TimelineAnnotation defaultInstance;
+    public static TimelineAnnotation getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public TimelineAnnotation getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private TimelineAnnotation(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              time_ = input.readInt64();
+              break;
+            }
+            case 18: {
+              bitField0_ |= 0x00000002;
+              message_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.class, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<TimelineAnnotation> PARSER =
+        new com.google.protobuf.AbstractParser<TimelineAnnotation>() {
+      public TimelineAnnotation parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new TimelineAnnotation(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<TimelineAnnotation> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required int64 time = 1;
+    public static final int TIME_FIELD_NUMBER = 1;
+    private long time_;
+    /**
+     * <code>required int64 time = 1;</code>
+     */
+    public boolean hasTime() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required int64 time = 1;</code>
+     */
+    public long getTime() {
+      return time_;
+    }
+
+    // required string message = 2;
+    public static final int MESSAGE_FIELD_NUMBER = 2;
+    private java.lang.Object message_;
+    /**
+     * <code>required string message = 2;</code>
+     */
+    public boolean hasMessage() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required string message = 2;</code>
+     */
+    public java.lang.String getMessage() {
+      java.lang.Object ref = message_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          message_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string message = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getMessageBytes() {
+      java.lang.Object ref = message_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        message_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      time_ = 0L;
+      message_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasTime()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasMessage()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, time_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getMessageBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, time_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getMessageBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation)) {
+        return super.equals(obj);
+      }
+      org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation other = (org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation) obj;
+
+      boolean result = true;
+      result = result && (hasTime() == other.hasTime());
+      if (hasTime()) {
+        result = result && (getTime()
+            == other.getTime());
+      }
+      result = result && (hasMessage() == other.hasMessage());
+      if (hasMessage()) {
+        result = result && getMessage()
+            .equals(other.getMessage());
+      }
+      result = result &&
+          getUnknownFields().equals(other.getUnknownFields());
+      return result;
+    }
+
+    private int memoizedHashCode = 0;
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptorForType().hashCode();
+      if (hasTime()) {
+        hash = (37 * hash) + TIME_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getTime());
+      }
+      if (hasMessage()) {
+        hash = (37 * hash) + MESSAGE_FIELD_NUMBER;
+        hash = (53 * hash) + getMessage().hashCode();
+      }
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code TimelineAnnotation}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.class, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder.class);
+      }
+
+      // Construct using org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        time_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        message_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_TimelineAnnotation_descriptor;
+      }
+
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getDefaultInstanceForType() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance();
+      }
+
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation build() {
+        org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation buildPartial() {
+        org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation result = new org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.time_ = time_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.message_ = message_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation) {
+          return mergeFrom((org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation other) {
+        if (other == org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance()) return this;
+        if (other.hasTime()) {
+          setTime(other.getTime());
+        }
+        if (other.hasMessage()) {
+          bitField0_ |= 0x00000002;
+          message_ = other.message_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasTime()) {
+          
+          return false;
+        }
+        if (!hasMessage()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required int64 time = 1;
+      private long time_ ;
+      /**
+       * <code>required int64 time = 1;</code>
+       */
+      public boolean hasTime() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required int64 time = 1;</code>
+       */
+      public long getTime() {
+        return time_;
+      }
+      /**
+       * <code>required int64 time = 1;</code>
+       */
+      public Builder setTime(long value) {
+        bitField0_ |= 0x00000001;
+        time_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 time = 1;</code>
+       */
+      public Builder clearTime() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        time_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required string message = 2;
+      private java.lang.Object message_ = "";
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public boolean hasMessage() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public java.lang.String getMessage() {
+        java.lang.Object ref = message_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          message_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getMessageBytes() {
+        java.lang.Object ref = message_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          message_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public Builder setMessage(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        message_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public Builder clearMessage() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        message_ = getDefaultInstance().getMessage();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string message = 2;</code>
+       */
+      public Builder setMessageBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        message_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:TimelineAnnotation)
+    }
+
+    static {
+      defaultInstance = new TimelineAnnotation(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:TimelineAnnotation)
+  }
+
+  public interface SpanOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required int64 trace_id = 1;
+    /**
+     * <code>required int64 trace_id = 1;</code>
+     */
+    boolean hasTraceId();
+    /**
+     * <code>required int64 trace_id = 1;</code>
+     */
+    long getTraceId();
+
+    // required int64 parent_id = 2;
+    /**
+     * <code>required int64 parent_id = 2;</code>
+     */
+    boolean hasParentId();
+    /**
+     * <code>required int64 parent_id = 2;</code>
+     */
+    long getParentId();
+
+    // required int64 start = 3;
+    /**
+     * <code>required int64 start = 3;</code>
+     */
+    boolean hasStart();
+    /**
+     * <code>required int64 start = 3;</code>
+     */
+    long getStart();
+
+    // required int64 stop = 4;
+    /**
+     * <code>required int64 stop = 4;</code>
+     */
+    boolean hasStop();
+    /**
+     * <code>required int64 stop = 4;</code>
+     */
+    long getStop();
+
+    // required int64 span_id = 5;
+    /**
+     * <code>required int64 span_id = 5;</code>
+     */
+    boolean hasSpanId();
+    /**
+     * <code>required int64 span_id = 5;</code>
+     */
+    long getSpanId();
+
+    // required string process_id = 6;
+    /**
+     * <code>required string process_id = 6;</code>
+     */
+    boolean hasProcessId();
+    /**
+     * <code>required string process_id = 6;</code>
+     */
+    java.lang.String getProcessId();
+    /**
+     * <code>required string process_id = 6;</code>
+     */
+    com.google.protobuf.ByteString
+        getProcessIdBytes();
+
+    // required string description = 7;
+    /**
+     * <code>required string description = 7;</code>
+     */
+    boolean hasDescription();
+    /**
+     * <code>required string description = 7;</code>
+     */
+    java.lang.String getDescription();
+    /**
+     * <code>required string description = 7;</code>
+     */
+    com.google.protobuf.ByteString
+        getDescriptionBytes();
+
+    // repeated .TimelineAnnotation timeline = 8;
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    java.util.List<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> 
+        getTimelineList();
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getTimeline(int index);
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    int getTimelineCount();
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    java.util.List<? extends org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
+        getTimelineOrBuilderList();
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder getTimelineOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code Span}
+   */
+  public static final class Span extends
+      com.google.protobuf.GeneratedMessage
+      implements SpanOrBuilder {
+    // Use Span.newBuilder() to construct.
+    private Span(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private Span(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final Span defaultInstance;
+    public static Span getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public Span getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private Span(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              traceId_ = input.readInt64();
+              break;
+            }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              parentId_ = input.readInt64();
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              start_ = input.readInt64();
+              break;
+            }
+            case 32: {
+              bitField0_ |= 0x00000008;
+              stop_ = input.readInt64();
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000010;
+              spanId_ = input.readInt64();
+              break;
+            }
+            case 50: {
+              bitField0_ |= 0x00000020;
+              processId_ = input.readBytes();
+              break;
+            }
+            case 58: {
+              bitField0_ |= 0x00000040;
+              description_ = input.readBytes();
+              break;
+            }
+            case 66: {
+              if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
+                timeline_ = new java.util.ArrayList<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation>();
+                mutable_bitField0_ |= 0x00000080;
+              }
+              timeline_.add(input.readMessage(org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.PARSER, extensionRegistry));
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
+          timeline_ = java.util.Collections.unmodifiableList(timeline_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_Span_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_Span_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.htrace.protobuf.generated.SpanProtos.Span.class, org.apache.htrace.protobuf.generated.SpanProtos.Span.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<Span> PARSER =
+        new com.google.protobuf.AbstractParser<Span>() {
+      public Span parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new Span(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Span> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required int64 trace_id = 1;
+    public static final int TRACE_ID_FIELD_NUMBER = 1;
+    private long traceId_;
+    /**
+     * <code>required int64 trace_id = 1;</code>
+     */
+    public boolean hasTraceId() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required int64 trace_id = 1;</code>
+     */
+    public long getTraceId() {
+      return traceId_;
+    }
+
+    // required int64 parent_id = 2;
+    public static final int PARENT_ID_FIELD_NUMBER = 2;
+    private long parentId_;
+    /**
+     * <code>required int64 parent_id = 2;</code>
+     */
+    public boolean hasParentId() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int64 parent_id = 2;</code>
+     */
+    public long getParentId() {
+      return parentId_;
+    }
+
+    // required int64 start = 3;
+    public static final int START_FIELD_NUMBER = 3;
+    private long start_;
+    /**
+     * <code>required int64 start = 3;</code>
+     */
+    public boolean hasStart() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required int64 start = 3;</code>
+     */
+    public long getStart() {
+      return start_;
+    }
+
+    // required int64 stop = 4;
+    public static final int STOP_FIELD_NUMBER = 4;
+    private long stop_;
+    /**
+     * <code>required int64 stop = 4;</code>
+     */
+    public boolean hasStop() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>required int64 stop = 4;</code>
+     */
+    public long getStop() {
+      return stop_;
+    }
+
+    // required int64 span_id = 5;
+    public static final int SPAN_ID_FIELD_NUMBER = 5;
+    private long spanId_;
+    /**
+     * <code>required int64 span_id = 5;</code>
+     */
+    public boolean hasSpanId() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>required int64 span_id = 5;</code>
+     */
+    public long getSpanId() {
+      return spanId_;
+    }
+
+    // required string process_id = 6;
+    public static final int PROCESS_ID_FIELD_NUMBER = 6;
+    private java.lang.Object processId_;
+    /**
+     * <code>required string process_id = 6;</code>
+     */
+    public boolean hasProcessId() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>required string process_id = 6;</code>
+     */
+    public java.lang.String getProcessId() {
+      java.lang.Object ref = processId_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          processId_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string process_id = 6;</code>
+     */
+    public com.google.protobuf.ByteString
+        getProcessIdBytes() {
+      java.lang.Object ref = processId_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        processId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // required string description = 7;
+    public static final int DESCRIPTION_FIELD_NUMBER = 7;
+    private java.lang.Object description_;
+    /**
+     * <code>required string description = 7;</code>
+     */
+    public boolean hasDescription() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>required string description = 7;</code>
+     */
+    public java.lang.String getDescription() {
+      java.lang.Object ref = description_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          description_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string description = 7;</code>
+     */
+    public com.google.protobuf.ByteString
+        getDescriptionBytes() {
+      java.lang.Object ref = description_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        description_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // repeated .TimelineAnnotation timeline = 8;
+    public static final int TIMELINE_FIELD_NUMBER = 8;
+    private java.util.List<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> timeline_;
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    public java.util.List<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> getTimelineList() {
+      return timeline_;
+    }
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    public java.util.List<? extends org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
+        getTimelineOrBuilderList() {
+      return timeline_;
+    }
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    public int getTimelineCount() {
+      return timeline_.size();
+    }
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getTimeline(int index) {
+      return timeline_.get(index);
+    }
+    /**
+     * <code>repeated .TimelineAnnotation timeline = 8;</code>
+     */
+    public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder getTimelineOrBuilder(
+        int index) {
+      return timeline_.get(index);
+    }
+
+    private void initFields() {
+      traceId_ = 0L;
+      parentId_ = 0L;
+      start_ = 0L;
+      stop_ = 0L;
+      spanId_ = 0L;
+      processId_ = "";
+      description_ = "";
+      timeline_ = java.util.Collections.emptyList();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasTraceId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasParentId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStart()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStop()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasSpanId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasProcessId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasDescription()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      for (int i = 0; i < getTimelineCount(); i++) {
+        if (!getTimeline(i).isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, traceId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt64(2, parentId_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt64(3, start_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeInt64(4, stop_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeInt64(5, spanId_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeBytes(6, getProcessIdBytes());
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeBytes(7, getDescriptionBytes());
+      }
+      for (int i = 0; i < timeline_.size(); i++) {
+        output.writeMessage(8, timeline_.get(i));
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, traceId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(2, parentId_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(3, start_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(4, stop_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(5, spanId_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(6, getProcessIdBytes());
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(7, getDescriptionBytes());
+      }
+      for (int i = 0; i < timeline_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(8, timeline_.get(i));
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof org.apache.htrace.protobuf.generated.SpanProtos.Span)) {
+        return super.equals(obj);
+      }
+      org.apache.htrace.protobuf.generated.SpanProtos.Span other = (org.apache.htrace.protobuf.generated.SpanProtos.Span) obj;
+
+      boolean result = true;
+      result = result && (hasTraceId() == other.hasTraceId());
+      if (hasTraceId()) {
+        result = result && (getTraceId()
+            == other.getTraceId());
+      }
+      result = result && (hasParentId() == other.hasParentId());
+      if (hasParentId()) {
+        result = result && (getParentId()
+            == other.getParentId());
+      }
+      result = result && (hasStart() == other.hasStart());
+      if (hasStart()) {
+        result = result && (getStart()
+            == other.getStart());
+      }
+      result = result && (hasStop() == other.hasStop());
+      if (hasStop()) {
+        result = result && (getStop()
+            == other.getStop());
+      }
+      result = result && (hasSpanId() == other.hasSpanId());
+      if (hasSpanId()) {
+        result = result && (getSpanId()
+            == other.getSpanId());
+      }
+      result = result && (hasProcessId() == other.hasProcessId());
+      if (hasProcessId()) {
+        result = result && getProcessId()
+            .equals(other.getProcessId());
+      }
+      result = result && (hasDescription() == other.hasDescription());
+      if (hasDescription()) {
+        result = result && getDescription()
+            .equals(other.getDescription());
+      }
+      result = result && getTimelineList()
+          .equals(other.getTimelineList());
+      result = result &&
+          getUnknownFields().equals(other.getUnknownFields());
+      return result;
+    }
+
+    private int memoizedHashCode = 0;
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptorForType().hashCode();
+      if (hasTraceId()) {
+        hash = (37 * hash) + TRACE_ID_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getTraceId());
+      }
+      if (hasParentId()) {
+        hash = (37 * hash) + PARENT_ID_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getParentId());
+      }
+      if (hasStart()) {
+        hash = (37 * hash) + START_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getStart());
+      }
+      if (hasStop()) {
+        hash = (37 * hash) + STOP_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getStop());
+      }
+      if (hasSpanId()) {
+        hash = (37 * hash) + SPAN_ID_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getSpanId());
+      }
+      if (hasProcessId()) {
+        hash = (37 * hash) + PROCESS_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getProcessId().hashCode();
+      }
+      if (hasDescription()) {
+        hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER;
+        hash = (53 * hash) + getDescription().hashCode();
+      }
+      if (getTimelineCount() > 0) {
+        hash = (37 * hash) + TIMELINE_FIELD_NUMBER;
+        hash = (53 * hash) + getTimelineList().hashCode();
+      }
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.htrace.protobuf.generated.SpanProtos.Span parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.htrace.protobuf.generated.SpanProtos.Span prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code Span}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.apache.htrace.protobuf.generated.SpanProtos.SpanOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_Span_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_Span_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.htrace.protobuf.generated.SpanProtos.Span.class, org.apache.htrace.protobuf.generated.SpanProtos.Span.Builder.class);
+      }
+
+      // Construct using org.apache.htrace.protobuf.generated.SpanProtos.Span.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getTimelineFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        traceId_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        parentId_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        start_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        stop_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        spanId_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        processId_ = "";
+        bitField0_ = (bitField0_ & ~0x00000020);
+        description_ = "";
+        bitField0_ = (bitField0_ & ~0x00000040);
+        if (timelineBuilder_ == null) {
+          timeline_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000080);
+        } else {
+          timelineBuilder_.clear();
+        }
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.internal_static_Span_descriptor;
+      }
+
+      public org.apache.htrace.protobuf.generated.SpanProtos.Span getDefaultInstanceForType() {
+        return org.apache.htrace.protobuf.generated.SpanProtos.Span.getDefaultInstance();
+      }
+
+      public org.apache.htrace.protobuf.generated.SpanProtos.Span build() {
+        org.apache.htrace.protobuf.generated.SpanProtos.Span result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.apache.htrace.protobuf.generated.SpanProtos.Span buildPartial() {
+        org.apache.htrace.protobuf.generated.SpanProtos.Span result = new org.apache.htrace.protobuf.generated.SpanProtos.Span(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.traceId_ = traceId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.parentId_ = parentId_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.start_ = start_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.stop_ = stop_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.spanId_ = spanId_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.processId_ = processId_;
+        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+          to_bitField0_ |= 0x00000040;
+        }
+        result.description_ = description_;
+        if (timelineBuilder_ == null) {
+          if (((bitField0_ & 0x00000080) == 0x00000080)) {
+            timeline_ = java.util.Collections.unmodifiableList(timeline_);
+            bitField0_ = (bitField0_ & ~0x00000080);
+          }
+          result.timeline_ = timeline_;
+        } else {
+          result.timeline_ = timelineBuilder_.build();
+        }
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.htrace.protobuf.generated.SpanProtos.Span) {
+          return mergeFrom((org.apache.htrace.protobuf.generated.SpanProtos.Span)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.apache.htrace.protobuf.generated.SpanProtos.Span other) {
+        if (other == org.apache.htrace.protobuf.generated.SpanProtos.Span.getDefaultInstance()) return this;
+        if (other.hasTraceId()) {
+          setTraceId(other.getTraceId());
+        }
+        if (other.hasParentId()) {
+          setParentId(other.getParentId());
+        }
+        if (other.hasStart()) {
+          setStart(other.getStart());
+        }
+        if (other.hasStop()) {
+          setStop(other.getStop());
+        }
+        if (other.hasSpanId()) {
+          setSpanId(other.getSpanId());
+        }
+        if (other.hasProcessId()) {
+          bitField0_ |= 0x00000020;
+          processId_ = other.processId_;
+          onChanged();
+        }
+        if (other.hasDescription()) {
+          bitField0_ |= 0x00000040;
+          description_ = other.description_;
+          onChanged();
+        }
+        if (timelineBuilder_ == null) {
+          if (!other.timeline_.isEmpty()) {
+            if (timeline_.isEmpty()) {
+              timeline_ = other.timeline_;
+              bitField0_ = (bitField0_ & ~0x00000080);
+            } else {
+              ensureTimelineIsMutable();
+              timeline_.addAll(other.timeline_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.timeline_.isEmpty()) {
+            if (timelineBuilder_.isEmpty()) {
+              timelineBuilder_.dispose();
+              timelineBuilder_ = null;
+              timeline_ = other.timeline_;
+              bitField0_ = (bitField0_ & ~0x00000080);
+              timelineBuilder_ = 
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getTimelineFieldBuilder() : null;
+            } else {
+              timelineBuilder_.addAllMessages(other.timeline_);
+            }
+          }
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasTraceId()) {
+          
+          return false;
+        }
+        if (!hasParentId()) {
+          
+          return false;
+        }
+        if (!hasStart()) {
+          
+          return false;
+        }
+        if (!hasStop()) {
+          
+          return false;
+        }
+        if (!hasSpanId()) {
+          
+          return false;
+        }
+        if (!hasProcessId()) {
+          
+          return false;
+        }
+        if (!hasDescription()) {
+          
+          return false;
+        }
+        for (int i = 0; i < getTimelineCount(); i++) {
+          if (!getTimeline(i).isInitialized()) {
+            
+            return false;
+          }
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.apache.htrace.protobuf.generated.SpanProtos.Span parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.apache.htrace.protobuf.generated.SpanProtos.Span) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required int64 trace_id = 1;
+      private long traceId_ ;
+      /**
+       * <code>required int64 trace_id = 1;</code>
+       */
+      public boolean hasTraceId() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required int64 trace_id = 1;</code>
+       */
+      public long getTraceId() {
+        return traceId_;
+      }
+      /**
+       * <code>required int64 trace_id = 1;</code>
+       */
+      public Builder setTraceId(long value) {
+        bitField0_ |= 0x00000001;
+        traceId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 trace_id = 1;</code>
+       */
+      public Builder clearTraceId() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        traceId_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int64 parent_id = 2;
+      private long parentId_ ;
+      /**
+       * <code>required int64 parent_id = 2;</code>
+       */
+      public boolean hasParentId() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required int64 parent_id = 2;</code>
+       */
+      public long getParentId() {
+        return parentId_;
+      }
+      /**
+       * <code>required int64 parent_id = 2;</code>
+       */
+      public Builder setParentId(long value) {
+        bitField0_ |= 0x00000002;
+        parentId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 parent_id = 2;</code>
+       */
+      public Builder clearParentId() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        parentId_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int64 start = 3;
+      private long start_ ;
+      /**
+       * <code>required int64 start = 3;</code>
+       */
+      public boolean hasStart() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>required int64 start = 3;</code>
+       */
+      public long getStart() {
+        return start_;
+      }
+      /**
+       * <code>required int64 start = 3;</code>
+       */
+      public Builder setStart(long value) {
+        bitField0_ |= 0x00000004;
+        start_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 start = 3;</code>
+       */
+      public Builder clearStart() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        start_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int64 stop = 4;
+      private long stop_ ;
+      /**
+       * <code>required int64 stop = 4;</code>
+       */
+      public boolean hasStop() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>required int64 stop = 4;</code>
+       */
+      public long getStop() {
+        return stop_;
+      }
+      /**
+       * <code>required int64 stop = 4;</code>
+       */
+      public Builder setStop(long value) {
+        bitField0_ |= 0x00000008;
+        stop_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 stop = 4;</code>
+       */
+      public Builder clearStop() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        stop_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int64 span_id = 5;
+      private long spanId_ ;
+      /**
+       * <code>required int64 span_id = 5;</code>
+       */
+      public boolean hasSpanId() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>required int64 span_id = 5;</code>
+       */
+      public long getSpanId() {
+        return spanId_;
+      }
+      /**
+       * <code>required int64 span_id = 5;</code>
+       */
+      public Builder setSpanId(long value) {
+        bitField0_ |= 0x00000010;
+        spanId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 span_id = 5;</code>
+       */
+      public Builder clearSpanId() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        spanId_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required string process_id = 6;
+      private java.lang.Object processId_ = "";
+      /**
+       * <code>required string process_id = 6;</code>
+       */
+      public boolean hasProcessId() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>required string process_id = 6;</code>
+       */
+      public java.lang.String getProcessId() {
+        java.lang.Object ref = processId_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          processId_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string process_id = 6;</code>
+       */
+      public com.google.protobuf.ByteString
+          getProcessIdBytes() {
+        java.lang.Object ref = processId_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          processId_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string process_id = 6;</code>
+       */
+      public Builder setProcessId(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        processId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string process_id = 6;</code>
+       */
+      public Builder clearProcessId() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        processId_ = getDefaultInstance().getProcessId();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string process_id = 6;</code>
+       */
+      public Builder setProcessIdBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        processId_ = value;
+        onChanged();
+        return this;
+      }
+
+      // required string description = 7;
+      private java.lang.Object description_ = "";
+      /**
+       * <code>required string description = 7;</code>
+       */
+      public boolean hasDescription() {
+        return ((bitField0_ & 0x00000040) == 0x00000040);
+      }
+      /**
+       * <code>required string description = 7;</code>
+       */
+      public java.lang.String getDescription() {
+        java.lang.Object ref = description_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          description_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string description = 7;</code>
+       */
+      public com.google.protobuf.ByteString
+          getDescriptionBytes() {
+        java.lang.Object ref = description_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          description_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string description = 7;</code>
+       */
+      public Builder setDescription(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000040;
+        description_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string description = 7;</code>
+       */
+      public Builder clearDescription() {
+        bitField0_ = (bitField0_ & ~0x00000040);
+        description_ = getDefaultInstance().getDescription();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string description = 7;</code>
+       */
+      public Builder setDescriptionBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000040;
+        description_ = value;
+        onChanged();
+        return this;
+      }
+
+      // repeated .TimelineAnnotation timeline = 8;
+      private java.util.List<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> timeline_ =
+        java.util.Collections.emptyList();
+      private void ensureTimelineIsMutable() {
+        if (!((bitField0_ & 0x00000080) == 0x00000080)) {
+          timeline_ = new java.util.ArrayList<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation>(timeline_);
+          bitField0_ |= 0x00000080;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> timelineBuilder_;
+
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public java.util.List<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> getTimelineList() {
+        if (timelineBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(timeline_);
+        } else {
+          return timelineBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public int getTimelineCount() {
+        if (timelineBuilder_ == null) {
+          return timeline_.size();
+        } else {
+          return timelineBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation getTimeline(int index) {
+        if (timelineBuilder_ == null) {
+          return timeline_.get(index);
+        } else {
+          return timelineBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder setTimeline(
+          int index, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation value) {
+        if (timelineBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureTimelineIsMutable();
+          timeline_.set(index, value);
+          onChanged();
+        } else {
+          timelineBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder setTimeline(
+          int index, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder builderForValue) {
+        if (timelineBuilder_ == null) {
+          ensureTimelineIsMutable();
+          timeline_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          timelineBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder addTimeline(org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation value) {
+        if (timelineBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureTimelineIsMutable();
+          timeline_.add(value);
+          onChanged();
+        } else {
+          timelineBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder addTimeline(
+          int index, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation value) {
+        if (timelineBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureTimelineIsMutable();
+          timeline_.add(index, value);
+          onChanged();
+        } else {
+          timelineBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder addTimeline(
+          org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder builderForValue) {
+        if (timelineBuilder_ == null) {
+          ensureTimelineIsMutable();
+          timeline_.add(builderForValue.build());
+          onChanged();
+        } else {
+          timelineBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder addTimeline(
+          int index, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder builderForValue) {
+        if (timelineBuilder_ == null) {
+          ensureTimelineIsMutable();
+          timeline_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          timelineBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder addAllTimeline(
+          java.lang.Iterable<? extends org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation> values) {
+        if (timelineBuilder_ == null) {
+          ensureTimelineIsMutable();
+          super.addAll(values, timeline_);
+          onChanged();
+        } else {
+          timelineBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder clearTimeline() {
+        if (timelineBuilder_ == null) {
+          timeline_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000080);
+          onChanged();
+        } else {
+          timelineBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public Builder removeTimeline(int index) {
+        if (timelineBuilder_ == null) {
+          ensureTimelineIsMutable();
+          timeline_.remove(index);
+          onChanged();
+        } else {
+          timelineBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder getTimelineBuilder(
+          int index) {
+        return getTimelineFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder getTimelineOrBuilder(
+          int index) {
+        if (timelineBuilder_ == null) {
+          return timeline_.get(index);  } else {
+          return timelineBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public java.util.List<? extends org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
+           getTimelineOrBuilderList() {
+        if (timelineBuilder_ != null) {
+          return timelineBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(timeline_);
+        }
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder addTimelineBuilder() {
+        return getTimelineFieldBuilder().addBuilder(
+            org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder addTimelineBuilder(
+          int index) {
+        return getTimelineFieldBuilder().addBuilder(
+            index, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .TimelineAnnotation timeline = 8;</code>
+       */
+      public java.util.List<org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder> 
+           getTimelineBuilderList() {
+        return getTimelineFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder> 
+          getTimelineFieldBuilder() {
+        if (timelineBuilder_ == null) {
+          timelineBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation.Builder, org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotationOrBuilder>(
+                  timeline_,
+                  ((bitField0_ & 0x00000080) == 0x00000080),
+                  getParentForChildren(),
+                  isClean());
+          timeline_ = null;
+        }
+        return timelineBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:Span)
+    }
+
+    static {
+      defaultInstance = new Span(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:Span)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_TimelineAnnotation_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_TimelineAnnotation_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_Span_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_Span_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\nSpan.proto\"3\n\022TimelineAnnotation\022\014\n\004ti" +
+      "me\030\001 \002(\003\022\017\n\007message\030\002 \002(\t\"\251\001\n\004Span\022\020\n\010tr" +
+      "ace_id\030\001 \002(\003\022\021\n\tparent_id\030\002 \002(\003\022\r\n\005start" +
+      "\030\003 \002(\003\022\014\n\004stop\030\004 \002(\003\022\017\n\007span_id\030\005 \002(\003\022\022\n" +
+      "\nprocess_id\030\006 \002(\t\022\023\n\013description\030\007 \002(\t\022%" +
+      "\n\010timeline\030\010 \003(\0132\023.TimelineAnnotationB0\n" +
+      "\035org.htrace.protobuf.generatedB\nSpanProt" +
+      "osH\001\240\001\001"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_TimelineAnnotation_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_TimelineAnnotation_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_TimelineAnnotation_descriptor,
+              new java.lang.String[] { "Time", "Message", });
+          internal_static_Span_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_Span_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_Span_descriptor,
+              new java.lang.String[] { "TraceId", "ParentId", "Start", "Stop", "SpanId", "ProcessId", "Description", "Timeline", });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewer.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewer.java b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewer.java
new file mode 100644
index 0000000..114ab4f
--- /dev/null
+++ b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewer.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.viewer;
+
+import com.google.protobuf.Message;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HConnection;
+import org.apache.hadoop.hbase.client.HConnectionManager;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.htrace.impl.HBaseSpanReceiver;
+import org.apache.htrace.protobuf.generated.SpanProtos;
+
+public class HBaseSpanViewer {
+  private static final Log LOG = LogFactory.getLog(HBaseSpanViewer.class);
+  private Configuration conf;
+  private HConnection hconnection;
+  private HTableInterface htable;
+  private byte[] table;
+  private byte[] cf; 
+  private byte[] icf; 
+
+  public HBaseSpanViewer(Configuration conf) {
+    this.conf = conf;
+    this.table = Bytes.toBytes(conf.get(HBaseSpanReceiver.TABLE_KEY,
+                                        HBaseSpanReceiver.DEFAULT_TABLE));
+    this.cf = Bytes.toBytes(conf.get(HBaseSpanReceiver.COLUMNFAMILY_KEY,
+                                     HBaseSpanReceiver.DEFAULT_COLUMNFAMILY));
+    this.icf = Bytes.toBytes(conf.get(HBaseSpanReceiver.INDEXFAMILY_KEY,
+                                      HBaseSpanReceiver.DEFAULT_INDEXFAMILY));
+  }
+
+  public void close() {
+    stopClient();
+  }
+
+  public void startClient() {
+    if (this.htable == null) {
+      try {
+        this.hconnection = HConnectionManager.createConnection(conf);
+        this.htable = hconnection.getTable(table);
+      } catch (IOException e) {
+        LOG.warn("Failed to create HBase connection. " + e.getMessage());
+      }
+    }
+  }
+
+  public void stopClient() {
+    try {
+      if (this.htable != null) {
+        this.htable.close();
+        this.htable = null;
+      }
+      if (this.hconnection != null) {
+        this.hconnection.close();
+        this.hconnection = null;
+      }
+    } catch (IOException e) {
+      LOG.warn("Failed to close HBase connection. " + e.getMessage());
+    }
+  }
+
+  public List<SpanProtos.Span> getSpans(long traceid) throws IOException {
+    startClient();
+    List<SpanProtos.Span> spans = new ArrayList<SpanProtos.Span>();
+    Get get = new Get(Bytes.toBytes(traceid));
+    get.addFamily(this.cf);
+    try {
+      for (Cell cell : htable.get(get).listCells()) {
+        InputStream in = new ByteArrayInputStream(cell.getQualifierArray(),
+                                                  cell.getQualifierOffset(),
+                                                  cell.getQualifierLength());
+        spans.add(SpanProtos.Span.parseFrom(in));
+      }
+    } catch (IOException e) {
+      LOG.warn("Failed to get spans from HBase. " + e.getMessage());
+      stopClient();
+    }
+    return spans;
+  }
+
+  public List<SpanProtos.Span> getRootSpans() throws IOException {
+    startClient();
+    Scan scan = new Scan();
+    scan.addColumn(this.icf, HBaseSpanReceiver.INDEX_SPAN_QUAL);
+    List<SpanProtos.Span> spans = new ArrayList<SpanProtos.Span>();
+    try {
+      ResultScanner scanner = htable.getScanner(scan);
+      Result result = null;
+      while ((result = scanner.next()) != null) {
+        for (Cell cell : result.listCells()) {
+          InputStream in = new ByteArrayInputStream(cell.getValueArray(),
+                                                    cell.getValueOffset(),
+                                                    cell.getValueLength());
+          spans.add(SpanProtos.Span.parseFrom(in));
+        }
+      }
+    } catch (IOException e) {
+      LOG.warn("Failed to get root spans from HBase. " + e.getMessage());
+      stopClient();
+    }
+    return spans;
+  }
+
+  public static String toJsonString(final Message message) throws IOException {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    OutputStreamWriter writer =
+        new OutputStreamWriter(out, Charset.defaultCharset());
+    appendJsonString(message, writer);
+    writer.flush();
+    out.flush();
+    return out.toString();
+  }
+
+  public static void appendJsonString(final Message message,
+                                        OutputStreamWriter writer) throws IOException {
+    writer.append("{");
+    for (Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+           message.getAllFields().entrySet().iterator(); iter.hasNext();) {
+      Map.Entry<FieldDescriptor, Object> field = iter.next();
+      appendFields(field.getKey(), field.getValue(), writer);
+      if (iter.hasNext()) {
+        writer.append(",");
+      }
+    }
+    writer.append("}");
+  }
+  
+
+  private static void appendFields(FieldDescriptor fd,
+                                   Object value, 
+                                   OutputStreamWriter writer) throws IOException {
+    writer.append("\"");
+    writer.append(fd.getName());
+    writer.append("\"");
+    writer.append(":");
+    if (fd.isRepeated()) {
+      writer.append("[");
+      for (Iterator<?> it = ((List<?>) value).iterator(); it.hasNext();) {
+        appendValue(fd, it.next(), writer);
+        if (it.hasNext()) {
+          writer.append(",");
+        }
+      }
+      writer.append("]");
+    } else {
+      appendValue(fd, value, writer);
+    }
+  }
+
+  private static void appendValue(FieldDescriptor fd,
+                                  Object value, 
+                                  OutputStreamWriter writer) throws IOException {
+    switch (fd.getType()) {
+    case INT64: // write int as string for handling in javascript
+    case STRING:
+      writer.append("\"");
+      writer.append(value.toString());
+      writer.append("\"");
+      break;
+    case MESSAGE:
+      appendJsonString((Message)value, writer);
+      break;
+    default:
+      throw new IOException("unexpected field type.");
+    }
+  }
+
+  /**
+   * Run basic test.
+   * @throws IOException
+   */
+  public static void main(String[] args) throws IOException {
+    HBaseSpanViewer viewer = new HBaseSpanViewer(HBaseConfiguration.create());
+    if (args.length == 0) {
+      List<SpanProtos.Span> spans = viewer.getRootSpans();
+      for (SpanProtos.Span span : spans) {
+        System.out.println(toJsonString(span));
+      }
+    } else {
+      List<SpanProtos.Span> spans = viewer.getSpans(Long.parseLong(args[0]));
+      for (SpanProtos.Span span : spans) {
+        System.out.println(toJsonString(span));
+      }
+    }
+    viewer.close();
+  }
+}


[2/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerServer.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerServer.java b/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerServer.java
deleted file mode 100644
index 3394b33..0000000
--- a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerServer.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.viewer;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.http.HttpServer2;
-import org.apache.hadoop.net.NetUtils;
-import org.apache.hadoop.util.Tool;
-import org.apache.hadoop.util.ToolRunner;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-
-public class HBaseSpanViewerServer implements Tool {
-  private static final Log LOG = LogFactory.getLog(HBaseSpanViewerServer.class);
-  public static final String HTRACE_VIEWER_HTTP_ADDRESS_KEY = "htrace.viewer.http.address";
-  public static final String HTRACE_VIEWER_HTTP_ADDRESS_DEFAULT = "0.0.0.0:16900";
-  public static final String HTRACE_CONF_ATTR = "htrace.conf";
-  public static final String HTRACE_APPDIR = "webapps";
-  public static final String NAME = "htrace";
-
-  private Configuration conf;
-  private HttpServer2 httpServer;
-  private InetSocketAddress httpAddress;
-
-  public void setConf(Configuration conf) {
-    this.conf = conf;
-  }
-
-  public Configuration getConf() {
-    return this.conf;
-  }
-
-  void start() throws IOException {
-    httpAddress = NetUtils.createSocketAddr(
-        conf.get(HTRACE_VIEWER_HTTP_ADDRESS_KEY, HTRACE_VIEWER_HTTP_ADDRESS_DEFAULT));
-    conf.set(HTRACE_VIEWER_HTTP_ADDRESS_KEY, NetUtils.getHostPortString(httpAddress));
-    HttpServer2.Builder builder = new HttpServer2.Builder();
-    builder.setName(NAME).setConf(conf);
-    if (httpAddress.getPort() == 0) {
-      builder.setFindPort(true);
-    }
-    URI uri = URI.create("http://" + NetUtils.getHostPortString(httpAddress));
-    builder.addEndpoint(uri);
-    LOG.info("Starting Web-server for " + NAME + " at: " + uri);
-    httpServer = builder.build();
-    httpServer.setAttribute(HTRACE_CONF_ATTR, conf);
-    httpServer.addServlet("gettraces",
-                          HBaseSpanViewerTracesServlet.PREFIX,
-                          HBaseSpanViewerTracesServlet.class);
-    httpServer.addServlet("getspans",
-                          HBaseSpanViewerSpansServlet.PREFIX + "/*",
-                          HBaseSpanViewerSpansServlet.class);
-
-    // for webapps/htrace bundled in jar.
-    String rb = httpServer.getClass()
-                          .getClassLoader()
-                          .getResource("webapps/" + NAME)
-                          .toString();
-    httpServer.getWebAppContext().setResourceBase(rb);
-
-    httpServer.start();
-    httpAddress = httpServer.getConnectorAddress(0);
-  }
-
-  void join() throws Exception {
-    if (httpServer != null) {
-      httpServer.join();
-    }
-  }
-
-  void stop() throws Exception {
-    if (httpServer != null) {
-      httpServer.stop();
-    }
-  }
-
-  InetSocketAddress getHttpAddress() {
-    return httpAddress;
-  }
-
-  public int run(String[] args) throws Exception {
-    start();
-    join();
-    stop();
-    return 0;
-  }
-
-  /**
-   * @throws IOException
-   */
-  public static void main(String[] args) throws Exception {
-    ToolRunner.run(HBaseConfiguration.create(), new HBaseSpanViewerServer(), args);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerSpansServlet.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerSpansServlet.java b/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerSpansServlet.java
deleted file mode 100644
index be4a79c..0000000
--- a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerSpansServlet.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.viewer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.util.ServletUtil;
-import org.htrace.protobuf.generated.SpanProtos;
-
-public class HBaseSpanViewerSpansServlet extends HttpServlet {
-  private static final Log LOG = LogFactory.getLog(HBaseSpanViewerSpansServlet.class);
-  public static final String PREFIX = "/getspans";
-  private static final ThreadLocal<HBaseSpanViewer> tlviewer =
-      new ThreadLocal<HBaseSpanViewer>() {
-        @Override
-        protected HBaseSpanViewer initialValue() {
-          return null;
-        }
-      };
-
-  @Override
-  @SuppressWarnings("unchecked")
-  public void doGet(HttpServletRequest request, HttpServletResponse response)
-      throws ServletException, IOException {
-    final String path =
-        validatePath(ServletUtil.getDecodedPath(request, PREFIX));
-    if (path == null) {
-      response.setContentType("text/plain");
-      response.getWriter().print("Invalid input");
-      return;
-    }
-    HBaseSpanViewer viewer = tlviewer.get();
-    if (viewer == null) {
-      final Configuration conf = (Configuration) getServletContext()
-        .getAttribute(HBaseSpanViewerServer.HTRACE_CONF_ATTR);
-      viewer = new HBaseSpanViewer(conf);
-      tlviewer.set(viewer);
-    }
-    Long traceid = Long.parseLong(path.substring(1));
-    response.setContentType("application/javascript");
-    PrintWriter out = response.getWriter();
-    out.print("[");
-    boolean first = true;
-    for (SpanProtos.Span span : viewer.getSpans(traceid)) {
-      if (first) {
-        first = false;
-      } else {
-        out.print(",");
-      }
-      out.print(HBaseSpanViewer.toJsonString(span));
-    }
-    out.print("]");
-  }
-
-  @Override
-  public void init() throws ServletException {
-  }
-
-  @Override
-  public void destroy() {
-    HBaseSpanViewer viewer = tlviewer.get();
-    if (viewer != null) {
-      viewer.close();
-    }
-  }
-
-  public static String validatePath(String p) {
-    return p == null || p.length() == 0?
-      null: new Path(p).toUri().getPath();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerTracesServlet.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerTracesServlet.java b/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerTracesServlet.java
deleted file mode 100644
index 3af49fc..0000000
--- a/htrace-hbase/src/main/java/org/htrace/viewer/HBaseSpanViewerTracesServlet.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.viewer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.util.ServletUtil;
-import org.htrace.protobuf.generated.SpanProtos;
-
-public class HBaseSpanViewerTracesServlet extends HttpServlet {
-  private static final Log LOG = LogFactory.getLog(HBaseSpanViewerTracesServlet.class);
-  public static final String PREFIX = "/gettraces";
-  private static final ThreadLocal<HBaseSpanViewer> tlviewer =
-      new ThreadLocal<HBaseSpanViewer>() {
-        @Override
-        protected HBaseSpanViewer initialValue() {
-          return null;
-        }
-      };
-
-  @Override
-  @SuppressWarnings("unchecked")
-  public void doGet(HttpServletRequest request, HttpServletResponse response)
-      throws ServletException, IOException {
-    HBaseSpanViewer viewer = tlviewer.get();
-    if (viewer == null) {
-      final Configuration conf = (Configuration) getServletContext()
-        .getAttribute(HBaseSpanViewerServer.HTRACE_CONF_ATTR);
-      viewer = new HBaseSpanViewer(conf);
-      tlviewer.set(viewer);
-    }
-    response.setContentType("application/javascript");
-    PrintWriter out = response.getWriter();
-    out.print("[");
-    boolean first = true;
-    for (SpanProtos.Span span : viewer.getRootSpans()) {
-      if (first) {
-        first = false;
-      } else {
-        out.print(",");
-      }
-      out.print(HBaseSpanViewer.toJsonString(span));
-    }
-    out.print("]");
-  }
-
-  @Override
-  public void init() throws ServletException {
-  }
-
-  @Override
-  public void destroy() {
-    HBaseSpanViewer viewer = tlviewer.get();
-    if (viewer != null) {
-      viewer.close();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/protobuf/Span.proto
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/protobuf/Span.proto b/htrace-hbase/src/main/protobuf/Span.proto
index 6e58b7c..e8dc369 100644
--- a/htrace-hbase/src/main/protobuf/Span.proto
+++ b/htrace-hbase/src/main/protobuf/Span.proto
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-option java_package = "org.htrace.protobuf.generated";
+option java_package = "org.apache.htrace.protobuf.generated";
 option java_outer_classname = "SpanProtos";
 option java_generate_equals_and_hash = true;
 option optimize_for = SPEED;

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/webapps/htrace/spans.js
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/webapps/htrace/spans.js b/htrace-hbase/src/main/webapps/htrace/spans.js
index c7c38af..03ff6fb 100644
--- a/htrace-hbase/src/main/webapps/htrace/spans.js
+++ b/htrace-hbase/src/main/webapps/htrace/spans.js
@@ -21,7 +21,7 @@ const width_span = 700;
 const size_tl = 6;
 const margin = {top: 50, bottom: 50, left: 50, right: 1000, process: 250};
 
-const ROOT_SPAN_ID = "477902"; // constants defined in org.htrace.Span
+const ROOT_SPAN_ID = "477902"; // constants defined in org.apache.htrace.Span
 const traceid = window.location.search.substring(1).split("=")[1];
 
 d3.json("/getspans/" + traceid, function(spans) {

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/test/java/org/apache/htrace/impl/HBaseTestUtil.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/test/java/org/apache/htrace/impl/HBaseTestUtil.java b/htrace-hbase/src/test/java/org/apache/htrace/impl/HBaseTestUtil.java
new file mode 100644
index 0000000..bcc5d27
--- /dev/null
+++ b/htrace-hbase/src/test/java/org/apache/htrace/impl/HBaseTestUtil.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.impl;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.trace.HBaseHTraceConfiguration;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.impl.HBaseSpanReceiver;
+import org.junit.Assert;
+
+
+public class HBaseTestUtil {
+  private static final Log LOG = LogFactory.getLog(HBaseTestUtil.class);
+
+  public static Configuration configure(Configuration conf) {
+    Configuration hconf = HBaseConfiguration.create(conf);
+    hconf.set(HBaseHTraceConfiguration.KEY_PREFIX +
+              HBaseSpanReceiver.COLLECTOR_QUORUM_KEY,
+              conf.get(HConstants.ZOOKEEPER_QUORUM));
+    hconf.setInt(HBaseHTraceConfiguration.KEY_PREFIX +
+                 HBaseSpanReceiver.ZOOKEEPER_CLIENT_PORT_KEY,
+                 conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 2181));
+    hconf.set(HBaseHTraceConfiguration.KEY_PREFIX +
+              HBaseSpanReceiver.ZOOKEEPER_ZNODE_PARENT_KEY,
+              conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT));
+    return hconf;
+  }
+
+  public static HTableInterface createTable(HBaseTestingUtility util) {
+    HTableInterface htable = null;
+    try {
+      htable = util.createTable(Bytes.toBytes(HBaseSpanReceiver.DEFAULT_TABLE),
+                                new byte[][]{Bytes.toBytes(HBaseSpanReceiver.DEFAULT_COLUMNFAMILY),
+                                             Bytes.toBytes(HBaseSpanReceiver.DEFAULT_INDEXFAMILY)});
+    } catch (IOException e) {
+      Assert.fail("failed to create htrace table. " + e.getMessage());
+    }
+    return htable;
+  }
+
+  public static SpanReceiver startReceiver(Configuration conf) {
+    /* TODO: FIX!!!!! CIRCULAR DEPENDENCY BACK TO HBASE
+    SpanReceiver receiver = new HBaseSpanReceiver();
+    receiver.configure(new HBaseHTraceConfiguration(conf));
+    return receiver;
+    */
+    return null;
+  }
+
+  public static SpanReceiver startReceiver(HBaseTestingUtility util) {
+    return startReceiver(configure(util.getConfiguration()));
+  }
+
+  public static void stopReceiver(SpanReceiver receiver) {
+    if (receiver != null) {
+      try {
+        receiver.close();
+        receiver = null;
+      } catch (IOException e) {
+        Assert.fail("failed to close span receiver. " + e.getMessage());
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/test/java/org/apache/htrace/impl/TestHBaseSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/test/java/org/apache/htrace/impl/TestHBaseSpanReceiver.java b/htrace-hbase/src/test/java/org/apache/htrace/impl/TestHBaseSpanReceiver.java
new file mode 100644
index 0000000..4d6d15c
--- /dev/null
+++ b/htrace-hbase/src/test/java/org/apache/htrace/impl/TestHBaseSpanReceiver.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.impl;
+
+import com.google.common.collect.Multimap;
+
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.TimelineAnnotation;
+import org.apache.htrace.TraceTree;
+import org.apache.htrace.impl.HBaseSpanReceiver;
+import org.apache.htrace.protobuf.generated.SpanProtos;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.Ignore;
+import org.junit.Assert;
+import org.apache.htrace.TraceCreator;
+
+
+public class TestHBaseSpanReceiver {
+  private static final Log LOG = LogFactory.getLog(TestHBaseSpanReceiver.class);
+  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    UTIL.startMiniCluster(1);
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    UTIL.shutdownMiniCluster();
+  }
+
+  // Reenable after fix circular dependency
+  @Ignore @Test
+  public void testHBaseSpanReceiver() {
+    HTableInterface htable = HBaseTestUtil.createTable(UTIL);
+    SpanReceiver receiver = HBaseTestUtil.startReceiver(UTIL);
+    TraceCreator tc = new TraceCreator(receiver);
+    tc.createThreadedTrace();
+    tc.createSimpleTrace();
+    tc.createSampleRpcTrace();
+    HBaseTestUtil.stopReceiver(receiver);
+    Scan scan = new Scan();
+    scan.addFamily(Bytes.toBytes(HBaseSpanReceiver.DEFAULT_COLUMNFAMILY));
+    scan.setMaxVersions(1);
+    ArrayList<Span> spans = new ArrayList<Span>();
+    try {
+      ResultScanner scanner = htable.getScanner(scan);
+      Result result = null;
+      while ((result = scanner.next()) != null) {
+        for (Cell cell : result.listCells()) {
+          InputStream in = new ByteArrayInputStream(cell.getQualifierArray(),
+                                                    cell.getQualifierOffset(),
+                                                    cell.getQualifierLength());
+          spans.add(new TestSpan(SpanProtos.Span.parseFrom(in)));
+        }
+      }
+    } catch (IOException e) {
+      Assert.fail("failed to get spans from HBase. " + e.getMessage());
+    }
+
+    TraceTree traceTree = new TraceTree(spans);
+    Collection<Span> roots = traceTree.getRoots();
+    Assert.assertEquals(3, roots.size());
+
+    Map<String, Span> descs = new HashMap<String, Span>();
+    for (Span root : roots) {
+      descs.put(root.getDescription(), root);
+    }
+    Assert.assertTrue(descs.keySet().contains(TraceCreator.RPC_TRACE_ROOT));
+    Assert.assertTrue(descs.keySet().contains(TraceCreator.SIMPLE_TRACE_ROOT));
+    Assert.assertTrue(descs.keySet().contains(TraceCreator.THREADED_TRACE_ROOT));
+
+    /** TODO: FIX!!!!!!
+    Multimap<Long, Span> spansByParentId = traceTree.getSpansByParentIdMap();
+    Span rpcRoot = descs.get(TraceCreator.RPC_TRACE_ROOT);
+    Assert.assertEquals(1, spansByParentId.get(rpcRoot.getSpanId()).size());
+    Span rpcChild1 = spansByParentId.get(rpcRoot.getSpanId()).iterator().next();
+    Assert.assertEquals(1, spansByParentId.get(rpcChild1.getSpanId()).size());
+    Span rpcChild2 = spansByParentId.get(rpcChild1.getSpanId()).iterator().next();
+    Assert.assertEquals(1, spansByParentId.get(rpcChild2.getSpanId()).size());
+    Span rpcChild3 = spansByParentId.get(rpcChild2.getSpanId()).iterator().next();
+    Assert.assertEquals(0, spansByParentId.get(rpcChild3.getSpanId()).size());
+
+    Scan iscan = new Scan();
+    iscan.addColumn(Bytes.toBytes(HBaseSpanReceiver.DEFAULT_INDEXFAMILY),
+                    HBaseSpanReceiver.INDEX_SPAN_QUAL);
+    try {
+      ResultScanner scanner = htable.getScanner(iscan);
+      Result result = null;
+      while ((result = scanner.next()) != null) {
+        for (Cell cell : result.listCells()) {
+          InputStream in = new ByteArrayInputStream(cell.getValueArray(),
+                                                    cell.getValueOffset(),
+                                                    cell.getValueLength());
+          Assert.assertEquals(SpanProtos.Span.parseFrom(in).getParentId(),
+                              Span.ROOT_SPAN_ID);
+        }
+      }
+    } catch (IOException e) {
+      Assert.fail("failed to get spans from index family. " + e.getMessage());
+    }
+      */
+  }
+
+  private class TestSpan implements Span {
+    SpanProtos.Span span;
+
+    public TestSpan(SpanProtos.Span span) {
+      this.span = span;
+    }
+
+    @Override
+    public long getTraceId() {
+      return span.getTraceId();
+    }
+
+    @Override
+    public long getParentId() {
+      return span.getParentId();
+    }
+
+    @Override
+    public long getStartTimeMillis() {
+      return span.getStart();
+    }
+
+    @Override
+    public long getStopTimeMillis() {
+      return span.getStop();
+    }
+
+    @Override
+    public long getSpanId() {
+      return span.getSpanId();
+    }
+
+    @Override
+    public String getProcessId() {
+      return span.getProcessId();
+    }
+
+    @Override
+    public String getDescription() {
+      return span.getDescription();
+    }
+
+    @Override
+    public String toString() {
+      return String.format("Span{Id:0x%16x,parentId:0x%16x,pid:%s,desc:%s}",
+                           getSpanId(), getParentId(),
+                           getProcessId(), getDescription());
+    }
+
+    @Override
+    public Map<byte[], byte[]> getKVAnnotations() {
+      return Collections.emptyMap();
+    }
+
+    @Override
+    public List<TimelineAnnotation> getTimelineAnnotations() {
+      return Collections.emptyList();
+    }
+
+    @Override
+    public void addKVAnnotation(byte[] key, byte[] value) {}
+
+    @Override
+    public void addTimelineAnnotation(String msg) {}
+
+    @Override
+    public synchronized void stop() {}
+
+    @Override
+    public synchronized boolean isRunning() {
+      return false;
+    }
+
+    @Override
+    public synchronized long getAccumulatedMillis() {
+      return span.getStop() - span.getStart();
+    }
+
+    @Override
+    public Span child(String description) {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/test/java/org/apache/htrace/viewer/TestHBaseSpanViewer.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/test/java/org/apache/htrace/viewer/TestHBaseSpanViewer.java b/htrace-hbase/src/test/java/org/apache/htrace/viewer/TestHBaseSpanViewer.java
new file mode 100644
index 0000000..21e603a
--- /dev/null
+++ b/htrace-hbase/src/test/java/org/apache/htrace/viewer/TestHBaseSpanViewer.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.viewer;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.htrace.protobuf.generated.SpanProtos.Span;
+import org.apache.htrace.protobuf.generated.SpanProtos.TimelineAnnotation;
+import org.apache.htrace.viewer.HBaseSpanViewer;
+import org.junit.Test;
+import org.junit.Assert;
+
+public class TestHBaseSpanViewer {
+  private static final Log LOG = LogFactory.getLog(TestHBaseSpanViewer.class);
+
+  @Test
+  public void testProtoToJson() {
+    Span.Builder sbuilder = Span.newBuilder();
+    TimelineAnnotation.Builder tlbuilder = TimelineAnnotation.newBuilder();
+    sbuilder.clear().setTraceId(1)
+                    .setParentId(2)
+                    .setStart(3)
+                    .setStop(4)
+                    .setSpanId(5)
+                    .setProcessId("pid")
+                    .setDescription("description");
+    for (int i = 0; i < 3; i++) {
+      sbuilder.addTimeline(tlbuilder.clear()
+                           .setTime(i)
+                           .setMessage("message" + i)
+                           .build());
+    }
+    Span span = sbuilder.build();
+    try {
+      String json = HBaseSpanViewer.toJsonString(span);
+      String expected =
+          "{\"trace_id\":\"1\","
+          + "\"parent_id\":\"2\","
+          + "\"start\":\"3\","
+          + "\"stop\":\"4\","
+          + "\"span_id\":\"5\","
+          + "\"process_id\":\"pid\","
+          + "\"description\":\"description\","
+          + "\"timeline\":["
+          + "{\"time\":\"0\",\"message\":\"message0\"},"
+          + "{\"time\":\"1\",\"message\":\"message1\"},"
+          + "{\"time\":\"2\",\"message\":\"message2\"}]}";
+      Assert.assertEquals(json, expected);
+    } catch (IOException e) {
+      Assert.fail("failed to get json from span. " + e.getMessage());
+    }
+  }
+
+  @Test
+  public void testProtoWithoutTimelineToJson() {
+    Span.Builder sbuilder = Span.newBuilder();
+    sbuilder.clear().setTraceId(1)
+                    .setParentId(2)
+                    .setStart(3)
+                    .setStop(4)
+                    .setSpanId(5)
+                    .setProcessId("pid")
+                    .setDescription("description");
+    Span span = sbuilder.build();
+    try {
+      String json = HBaseSpanViewer.toJsonString(span);
+      String expected =
+          "{\"trace_id\":\"1\","
+          + "\"parent_id\":\"2\","
+          + "\"start\":\"3\","
+          + "\"stop\":\"4\","
+          + "\"span_id\":\"5\","
+          + "\"process_id\":\"pid\","
+          + "\"description\":\"description\"}";
+      Assert.assertEquals(json, expected);
+    } catch (IOException e) {
+      Assert.fail("failed to get json from span. " + e.getMessage());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/test/java/org/htrace/impl/HBaseTestUtil.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/test/java/org/htrace/impl/HBaseTestUtil.java b/htrace-hbase/src/test/java/org/htrace/impl/HBaseTestUtil.java
deleted file mode 100644
index 5e8436b..0000000
--- a/htrace-hbase/src/test/java/org/htrace/impl/HBaseTestUtil.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.impl;
-
-import java.io.IOException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.trace.HBaseHTraceConfiguration;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.junit.Assert;
-import org.htrace.SpanReceiver;
-import org.htrace.HTraceConfiguration;
-
-
-public class HBaseTestUtil {
-  private static final Log LOG = LogFactory.getLog(HBaseTestUtil.class);
-
-  public static Configuration configure(Configuration conf) {
-    Configuration hconf = HBaseConfiguration.create(conf);
-    hconf.set(HBaseHTraceConfiguration.KEY_PREFIX +
-              HBaseSpanReceiver.COLLECTOR_QUORUM_KEY,
-              conf.get(HConstants.ZOOKEEPER_QUORUM));
-    hconf.setInt(HBaseHTraceConfiguration.KEY_PREFIX +
-                 HBaseSpanReceiver.ZOOKEEPER_CLIENT_PORT_KEY,
-                 conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 2181));
-    hconf.set(HBaseHTraceConfiguration.KEY_PREFIX +
-              HBaseSpanReceiver.ZOOKEEPER_ZNODE_PARENT_KEY,
-              conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT));
-    return hconf;
-  }
-
-  public static HTableInterface createTable(HBaseTestingUtility util) {
-    HTableInterface htable = null;
-    try { 
-      htable = util.createTable(Bytes.toBytes(HBaseSpanReceiver.DEFAULT_TABLE),
-                                new byte[][]{Bytes.toBytes(HBaseSpanReceiver.DEFAULT_COLUMNFAMILY),
-                                             Bytes.toBytes(HBaseSpanReceiver.DEFAULT_INDEXFAMILY)});
-    } catch (IOException e) {
-      Assert.fail("failed to create htrace table. " + e.getMessage());
-    }
-    return htable;
-  }
-
-  public static SpanReceiver startReceiver(Configuration conf) {
-    SpanReceiver receiver = new HBaseSpanReceiver();
-    receiver.configure(new HBaseHTraceConfiguration(conf));
-    return receiver;
-  }
-
-  public static SpanReceiver startReceiver(HBaseTestingUtility util) {
-    return startReceiver(configure(util.getConfiguration()));
-  }
-
-  public static void stopReceiver(SpanReceiver receiver) {
-    if (receiver != null) {
-      try {
-        receiver.close();
-        receiver = null;
-      } catch (IOException e) {
-        Assert.fail("failed to close span receiver. " + e.getMessage());
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/test/java/org/htrace/impl/TestHBaseSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/test/java/org/htrace/impl/TestHBaseSpanReceiver.java b/htrace-hbase/src/test/java/org/htrace/impl/TestHBaseSpanReceiver.java
deleted file mode 100644
index a247f05..0000000
--- a/htrace-hbase/src/test/java/org/htrace/impl/TestHBaseSpanReceiver.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.impl;
-
-import com.google.common.collect.Multimap;
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.Cell;
-import org.apache.hadoop.hbase.CellUtil;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.Assert;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-import org.htrace.TimelineAnnotation;
-import org.htrace.TraceCreator;
-import org.htrace.TraceTree;
-import org.htrace.protobuf.generated.SpanProtos;
-
-
-public class TestHBaseSpanReceiver {
-  private static final Log LOG = LogFactory.getLog(TestHBaseSpanReceiver.class);
-  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
-
-  @BeforeClass
-  public static void setUpBeforeClass() throws Exception {
-    UTIL.startMiniCluster(1);
-  }
-
-  @AfterClass
-  public static void tearDownAfterClass() throws Exception {
-    UTIL.shutdownMiniCluster();
-  }
-
-  @Test
-  public void testHBaseSpanReceiver() {
-    HTableInterface htable = HBaseTestUtil.createTable(UTIL);
-    SpanReceiver receiver = HBaseTestUtil.startReceiver(UTIL);
-    TraceCreator tc = new TraceCreator(receiver);
-    tc.createThreadedTrace();
-    tc.createSimpleTrace();
-    tc.createSampleRpcTrace();
-    HBaseTestUtil.stopReceiver(receiver);
-    Scan scan = new Scan();
-    scan.addFamily(Bytes.toBytes(HBaseSpanReceiver.DEFAULT_COLUMNFAMILY));
-    scan.setMaxVersions(1);
-    ArrayList<Span> spans = new ArrayList<Span>();
-    try {
-      ResultScanner scanner = htable.getScanner(scan);
-      Result result = null;
-      while ((result = scanner.next()) != null) {
-        for (Cell cell : result.listCells()) {
-          InputStream in = new ByteArrayInputStream(cell.getQualifierArray(),
-                                                    cell.getQualifierOffset(),
-                                                    cell.getQualifierLength());
-          spans.add(new TestSpan(SpanProtos.Span.parseFrom(in)));
-        }
-      }
-    } catch (IOException e) {
-      Assert.fail("failed to get spans from HBase. " + e.getMessage());
-    }
-
-    TraceTree traceTree = new TraceTree(spans);
-    Collection<Span> roots = traceTree.getRoots();
-    Assert.assertEquals(3, roots.size());
-
-    Map<String, Span> descs = new HashMap<String, Span>();
-    for (Span root : roots) {
-      descs.put(root.getDescription(), root);
-    }
-    Assert.assertTrue(descs.keySet().contains(TraceCreator.RPC_TRACE_ROOT));
-    Assert.assertTrue(descs.keySet().contains(TraceCreator.SIMPLE_TRACE_ROOT));
-    Assert.assertTrue(descs.keySet().contains(TraceCreator.THREADED_TRACE_ROOT));
-
-    Multimap<Long, Span> spansByParentId = traceTree.getSpansByParentIdMap();
-    Span rpcRoot = descs.get(TraceCreator.RPC_TRACE_ROOT);
-    Assert.assertEquals(1, spansByParentId.get(rpcRoot.getSpanId()).size());
-    Span rpcChild1 = spansByParentId.get(rpcRoot.getSpanId()).iterator().next();
-    Assert.assertEquals(1, spansByParentId.get(rpcChild1.getSpanId()).size());
-    Span rpcChild2 = spansByParentId.get(rpcChild1.getSpanId()).iterator().next();
-    Assert.assertEquals(1, spansByParentId.get(rpcChild2.getSpanId()).size());
-    Span rpcChild3 = spansByParentId.get(rpcChild2.getSpanId()).iterator().next();
-    Assert.assertEquals(0, spansByParentId.get(rpcChild3.getSpanId()).size());
-
-    Scan iscan = new Scan();
-    iscan.addColumn(Bytes.toBytes(HBaseSpanReceiver.DEFAULT_INDEXFAMILY),
-                    HBaseSpanReceiver.INDEX_SPAN_QUAL);
-    try {
-      ResultScanner scanner = htable.getScanner(iscan);
-      Result result = null;
-      while ((result = scanner.next()) != null) {
-        for (Cell cell : result.listCells()) {
-          InputStream in = new ByteArrayInputStream(cell.getValueArray(),
-                                                    cell.getValueOffset(),
-                                                    cell.getValueLength());
-          Assert.assertEquals(SpanProtos.Span.parseFrom(in).getParentId(),
-                              Span.ROOT_SPAN_ID);
-        }
-      }
-    } catch (IOException e) {
-      Assert.fail("failed to get spans from index family. " + e.getMessage());
-    }
-  }
-
-  private class TestSpan implements Span {
-    SpanProtos.Span span;
-
-    public TestSpan(SpanProtos.Span span) {
-      this.span = span;
-    }
-    
-    @Override
-    public long getTraceId() {
-      return span.getTraceId();
-    }
-  
-    @Override
-    public long getParentId() {
-      return span.getParentId();
-    }
-  
-    @Override
-    public long getStartTimeMillis() {
-      return span.getStart();
-    }
-  
-    @Override
-    public long getStopTimeMillis() {
-      return span.getStop();
-    }
-  
-    @Override
-    public long getSpanId() {
-      return span.getSpanId();
-    }
-  
-    @Override
-    public String getProcessId() {
-      return span.getProcessId();
-    }
-  
-    @Override
-    public String getDescription() {
-      return span.getDescription();
-    }
-  
-    @Override
-    public String toString() {
-      return String.format("Span{Id:0x%16x,parentId:0x%16x,pid:%s,desc:%s}",
-                           getSpanId(), getParentId(),
-                           getProcessId(), getDescription());
-    }
-  
-    @Override
-    public Map<byte[], byte[]> getKVAnnotations() {
-      return Collections.emptyMap();
-    }
-  
-    @Override
-    public List<TimelineAnnotation> getTimelineAnnotations() {
-      return Collections.emptyList();
-    }
-  
-    @Override
-    public void addKVAnnotation(byte[] key, byte[] value) {}
-  
-    @Override
-    public void addTimelineAnnotation(String msg) {}
-  
-    @Override
-    public synchronized void stop() {}
-  
-    @Override
-    public synchronized boolean isRunning() {
-      return false;
-    }
-    
-    @Override
-    public synchronized long getAccumulatedMillis() {
-      return span.getStop() - span.getStart();
-    }
-  
-    @Override
-    public Span child(String description) {
-      return null;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/test/java/org/htrace/viewer/TestHBaseSpanViewer.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/test/java/org/htrace/viewer/TestHBaseSpanViewer.java b/htrace-hbase/src/test/java/org/htrace/viewer/TestHBaseSpanViewer.java
deleted file mode 100644
index 9c5515c..0000000
--- a/htrace-hbase/src/test/java/org/htrace/viewer/TestHBaseSpanViewer.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.viewer;
-
-import java.io.IOException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.Test;
-import org.junit.Assert;
-import org.htrace.protobuf.generated.SpanProtos.Span;
-import org.htrace.protobuf.generated.SpanProtos.TimelineAnnotation;
-
-public class TestHBaseSpanViewer {
-  private static final Log LOG = LogFactory.getLog(TestHBaseSpanViewer.class);
-
-  @Test
-  public void testProtoToJson() {
-    Span.Builder sbuilder = Span.newBuilder();
-    TimelineAnnotation.Builder tlbuilder = TimelineAnnotation.newBuilder();
-    sbuilder.clear().setTraceId(1)
-                    .setParentId(2)
-                    .setStart(3)
-                    .setStop(4)
-                    .setSpanId(5)
-                    .setProcessId("pid")
-                    .setDescription("description");
-    for (int i = 0; i < 3; i++) {
-      sbuilder.addTimeline(tlbuilder.clear()
-                           .setTime(i)
-                           .setMessage("message" + i)
-                           .build());
-    }
-    Span span = sbuilder.build();
-    try {
-      String json = HBaseSpanViewer.toJsonString(span);
-      String expected =
-          "{\"trace_id\":\"1\","
-          + "\"parent_id\":\"2\","
-          + "\"start\":\"3\","
-          + "\"stop\":\"4\","
-          + "\"span_id\":\"5\","
-          + "\"process_id\":\"pid\","
-          + "\"description\":\"description\","
-          + "\"timeline\":["
-          + "{\"time\":\"0\",\"message\":\"message0\"},"
-          + "{\"time\":\"1\",\"message\":\"message1\"},"
-          + "{\"time\":\"2\",\"message\":\"message2\"}]}";
-      Assert.assertEquals(json, expected);
-    } catch (IOException e) {
-      Assert.fail("failed to get json from span. " + e.getMessage());
-    }
-  }
-
-  @Test
-  public void testProtoWithoutTimelineToJson() {
-    Span.Builder sbuilder = Span.newBuilder();
-    sbuilder.clear().setTraceId(1)
-                    .setParentId(2)
-                    .setStart(3)
-                    .setStop(4)
-                    .setSpanId(5)
-                    .setProcessId("pid")
-                    .setDescription("description");
-    Span span = sbuilder.build();
-    try {
-      String json = HBaseSpanViewer.toJsonString(span);
-      String expected =
-          "{\"trace_id\":\"1\","
-          + "\"parent_id\":\"2\","
-          + "\"start\":\"3\","
-          + "\"stop\":\"4\","
-          + "\"span_id\":\"5\","
-          + "\"process_id\":\"pid\","
-          + "\"description\":\"description\"}";
-      Assert.assertEquals(json, expected);
-    } catch (IOException e) {
-      Assert.fail("failed to get json from span. " + e.getMessage());
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/pom.xml
----------------------------------------------------------------------
diff --git a/htrace-zipkin/pom.xml b/htrace-zipkin/pom.xml
index d9f8116..81b712e 100644
--- a/htrace-zipkin/pom.xml
+++ b/htrace-zipkin/pom.xml
@@ -17,7 +17,7 @@ language governing permissions and limitations under the License. -->
 
   <parent>
     <artifactId>htrace</artifactId>
-    <groupId>org.htrace</groupId>
+    <groupId>org.apache.htrace</groupId>
     <version>3.0.4</version>
   </parent>
 
@@ -66,7 +66,7 @@ language governing permissions and limitations under the License. -->
   <dependencies>
     <!-- Module deps. -->
     <dependency>
-      <groupId>org.htrace</groupId>
+      <groupId>org.apache.htrace</groupId>
       <artifactId>htrace-core</artifactId>
       <version>${project.version}</version>
       <scope>provided</scope>

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/src/main/java/org/apache/htrace/impl/ZipkinSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-zipkin/src/main/java/org/apache/htrace/impl/ZipkinSpanReceiver.java b/htrace-zipkin/src/main/java/org/apache/htrace/impl/ZipkinSpanReceiver.java
new file mode 100644
index 0000000..86f32f7
--- /dev/null
+++ b/htrace-zipkin/src/main/java/org/apache/htrace/impl/ZipkinSpanReceiver.java
@@ -0,0 +1,363 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.impl;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.twitter.zipkin.gen.LogEntry;
+import com.twitter.zipkin.gen.Scribe;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.zipkin.HTraceToZipkinConverter;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.protocol.TProtocolFactory;
+import org.apache.thrift.transport.TFramedTransport;
+import org.apache.thrift.transport.TIOStreamTransport;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TTransportException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Zipkin is an open source tracing library. This span receiver acts as a bridge between HTrace and
+ * Zipkin, that converts HTrace Span objects into Zipkin Span objects.
+ * <p/>
+ * HTrace spans are queued into a blocking queue.  From there background worker threads will
+ * batch the spans together and then send them through to a Zipkin collector.
+ */
+public class ZipkinSpanReceiver implements SpanReceiver {
+  private static final Log LOG = LogFactory.getLog(ZipkinSpanReceiver.class);
+
+  /**
+   * Default hostname to fall back on.
+   */
+  private static final String DEFAULT_COLLECTOR_HOSTNAME = "localhost";
+
+  /**
+   * Default collector port.
+   */
+  private static final int DEFAULT_COLLECTOR_PORT = 9410; // trace collector default port.
+
+  /**
+   * this is used to tell scribe that the entries are for zipkin..
+   */
+  private static final String CATEGORY = "zipkin";
+
+  /**
+   * Whether the service which is traced is in client or a server mode. It is used while creating
+   * the Endpoint.
+   */
+  private static final boolean DEFAULT_IN_CLIENT_MODE = false;
+
+  /**
+   * How long this receiver will try and wait for all threads to shutdown.
+   */
+  private static final int SHUTDOWN_TIMEOUT = 30;
+
+  /**
+   * How many spans this receiver will try and send in one batch.
+   */
+  private static final int MAX_SPAN_BATCH_SIZE = 100;
+
+  /**
+   * How many errors in a row before we start dropping traces on the floor.
+   */
+  private static final int MAX_ERRORS = 10;
+
+  /**
+   * The queue that will get all HTrace spans that are to be sent.
+   */
+  private final BlockingQueue<Span> queue;
+
+  /**
+   * Factory used to encode a Zipkin Span to bytes.
+   */
+  private final TProtocolFactory protocolFactory;
+
+  /**
+   * Boolean used to signal that the threads should end.
+   */
+  private final AtomicBoolean running = new AtomicBoolean(true);
+
+  /**
+   * The thread factory used to create new ExecutorService.
+   * <p/>
+   * This will be the same factory for the lifetime of this object so that
+   * no thread names will ever be duplicated.
+   */
+  private final ThreadFactory tf;
+
+  ////////////////////
+  /// Variables that will change on each call to configure()
+  ///////////////////
+  private HTraceToZipkinConverter converter;
+  private ExecutorService service;
+  private HTraceConfiguration conf;
+  private String collectorHostname;
+  private int collectorPort;
+
+  public ZipkinSpanReceiver() {
+    this.queue = new ArrayBlockingQueue<Span>(1000);
+    this.protocolFactory = new TBinaryProtocol.Factory();
+
+    tf = new ThreadFactoryBuilder().setDaemon(true)
+        .setNameFormat("zipkinSpanReceiver-%d")
+        .build();
+  }
+
+  @Override
+  public void configure(HTraceConfiguration conf) {
+    this.conf = conf;
+
+    this.collectorHostname = conf.get("zipkin.collector-hostname",
+        DEFAULT_COLLECTOR_HOSTNAME);
+    this.collectorPort = conf.getInt("zipkin.collector-port",
+        DEFAULT_COLLECTOR_PORT);
+
+    // initialize the endpoint. This endpoint is used while writing the Span.
+    initConverter();
+
+    int numThreads = conf.getInt("zipkin.num-threads", 1);
+
+    // If there are already threads runnnig tear them down.
+    if (this.service != null) {
+      this.service.shutdownNow();
+      this.service = null;
+    }
+
+    this.service = Executors.newFixedThreadPool(numThreads, tf);
+
+    for (int i = 0; i < numThreads; i++) {
+      this.service.submit(new WriteSpanRunnable());
+    }
+  }
+
+  /**
+   * Set up the HTrace to Zipkin converter.
+   */
+  private void initConverter() {
+    InetAddress tracedServiceHostname = null;
+    // Try and get the hostname.  If it's not configured try and get the local hostname.
+    try {
+      String host = conf.get("zipkin.traced-service-hostname",
+          InetAddress.getLocalHost().getHostAddress());
+
+      tracedServiceHostname = InetAddress.getByName(host);
+    } catch (UnknownHostException e) {
+      LOG.error("Couldn't get the localHost address", e);
+    }
+    short tracedServicePort = (short) conf.getInt("zipkin.traced-service-port", -1);
+    byte[] address = tracedServiceHostname != null
+        ? tracedServiceHostname.getAddress() : DEFAULT_COLLECTOR_HOSTNAME.getBytes();
+    int ipv4 = ByteBuffer.wrap(address).getInt();
+    this.converter = new HTraceToZipkinConverter(ipv4, tracedServicePort);
+  }
+
+
+  private class WriteSpanRunnable implements Runnable {
+    /**
+     * scribe client to push zipkin spans
+     */
+    private Scribe.Client scribeClient = null;
+    private final ByteArrayOutputStream baos;
+    private final TProtocol streamProtocol;
+
+    public WriteSpanRunnable() {
+      baos = new ByteArrayOutputStream();
+      streamProtocol = protocolFactory.getProtocol(new TIOStreamTransport(baos));
+    }
+
+    /**
+     * This runnable converts a HTrace span to a Zipkin span and sends it across the zipkin
+     * collector as a thrift object. The scribe client which is used for rpc writes a list of
+     * LogEntry objects, so the span objects are first transformed into LogEntry objects before
+     * sending to the zipkin-collector.
+     * <p/>
+     * Here is a little ascii art which shows the above transformation:
+     * <pre>
+     *  +------------+   +------------+   +------------+              +-----------------+
+     *  | HTrace Span|-->|Zipkin Span |-->| (LogEntry) | ===========> | Zipkin Collector|
+     *  +------------+   +------------+   +------------+ (Scribe rpc) +-----------------+
+     *  </pre>
+     */
+    @Override
+    public void run() {
+
+      List<Span> dequeuedSpans = new ArrayList<Span>(MAX_SPAN_BATCH_SIZE);
+
+      long errorCount = 0;
+
+      while (running.get() || queue.size() > 0) {
+        Span firstSpan = null;
+        try {
+          // Block for up to a second. to try and get a span.
+          // We only block for a little bit in order to notice if the running value has changed
+          firstSpan = queue.poll(1, TimeUnit.SECONDS);
+
+          // If the poll was successful then it's possible that there
+          // will be other spans to get. Try and get them.
+          if (firstSpan != null) {
+            // Add the first one that we got
+            dequeuedSpans.add(firstSpan);
+            // Try and get up to 100 queues
+            queue.drainTo(dequeuedSpans, MAX_SPAN_BATCH_SIZE - 1);
+          }
+
+        } catch (InterruptedException ie) {
+          // Ignored.
+        }
+
+        if (dequeuedSpans.isEmpty()) continue;
+
+        // If this is the first time through or there was an error re-connect
+        if (scribeClient == null) {
+          startClient();
+        }
+        // Create a new list every time through so that the list doesn't change underneath
+        // thrift as it's sending.
+        List<LogEntry> entries = new ArrayList<LogEntry>(dequeuedSpans.size());
+        try {
+          // Convert every de-queued span
+          for (Span htraceSpan : dequeuedSpans) {
+            // convert the HTrace span to Zipkin span
+            com.twitter.zipkin.gen.Span zipkinSpan = converter.convert(htraceSpan);
+            // Clear any old data.
+            baos.reset();
+            // Write the span to a BAOS
+            zipkinSpan.write(streamProtocol);
+
+            // Do Base64 encoding and put the string into a log entry.
+            LogEntry logEntry =
+                new LogEntry(CATEGORY, Base64.encodeBase64String(baos.toByteArray()));
+            entries.add(logEntry);
+          }
+
+          // Send the entries
+          scribeClient.Log(entries);
+          // clear the list for the next time through.
+          dequeuedSpans.clear();
+          // reset the error counter.
+          errorCount = 0;
+        } catch (Exception e) {
+          LOG.error("Error when writing to the zipkin collector: " +
+              collectorHostname + ":" + collectorPort, e);
+
+          errorCount += 1;
+          // If there have been ten errors in a row start dropping things.
+          if (errorCount < MAX_ERRORS) {
+            try {
+              queue.addAll(dequeuedSpans);
+            } catch (IllegalStateException ex) {
+              LOG.error("Drop " + dequeuedSpans.size() + " span(s) because queue is full");
+            }
+          }
+
+          closeClient();
+          try {
+            // Since there was an error sleep just a little bit to try and allow the
+            // zipkin collector some time to recover.
+            Thread.sleep(500);
+          } catch (InterruptedException e1) {
+            // Ignored
+          }
+        }
+      }
+      closeClient();
+    }
+
+    /**
+     * Close out the connection.
+     */
+    private void closeClient() {
+      // close out the transport.
+      if (scribeClient != null) {
+        scribeClient.getInputProtocol().getTransport().close();
+        scribeClient = null;
+      }
+    }
+
+    /**
+     * Re-connect to Zipkin.
+     */
+    private void startClient() {
+      if (this.scribeClient == null) {
+        TTransport transport = new TFramedTransport(new TSocket(collectorHostname, collectorPort));
+        try {
+          transport.open();
+        } catch (TTransportException e) {
+          e.printStackTrace();
+        }
+        TProtocol protocol = protocolFactory.getProtocol(transport);
+        this.scribeClient = new Scribe.Client(protocol);
+      }
+    }
+  }
+
+  /**
+   * Close the receiver.
+   * <p/>
+   * This tries to shut
+   *
+   * @throws IOException
+   */
+  @Override
+  public void close() throws IOException {
+    running.set(false);
+    service.shutdown();
+    try {
+      if (!service.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
+        LOG.error("Was not able to process all remaining spans to write upon closing in: " +
+            SHUTDOWN_TIMEOUT + " " + TimeUnit.SECONDS + ". There could be un-sent spans still left." +
+            "  They have been dropped.");
+      }
+    } catch (InterruptedException e1) {
+      LOG.warn("Thread interrupted when terminating executor.", e1);
+    }
+  }
+
+  @Override
+  public void receiveSpan(Span span) {
+    if (running.get()) {
+      try {
+        this.queue.add(span);
+      } catch (IllegalStateException e) {
+        LOG.error("Error trying to append span (" + span.getDescription() + ") to the queue."
+            + "  Blocking Queue was full.");
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/src/main/java/org/apache/htrace/zipkin/HTraceToZipkinConverter.java
----------------------------------------------------------------------
diff --git a/htrace-zipkin/src/main/java/org/apache/htrace/zipkin/HTraceToZipkinConverter.java b/htrace-zipkin/src/main/java/org/apache/htrace/zipkin/HTraceToZipkinConverter.java
new file mode 100644
index 0000000..09ab1ea
--- /dev/null
+++ b/htrace-zipkin/src/main/java/org/apache/htrace/zipkin/HTraceToZipkinConverter.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.zipkin;
+
+import com.twitter.zipkin.gen.Annotation;
+import com.twitter.zipkin.gen.AnnotationType;
+import com.twitter.zipkin.gen.BinaryAnnotation;
+import com.twitter.zipkin.gen.Endpoint;
+import com.twitter.zipkin.gen.Span;
+import com.twitter.zipkin.gen.zipkinCoreConstants;
+
+import org.apache.htrace.TimelineAnnotation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is responsible for converting a HTrace.Span to a Zipkin.Span object. To use the Zipkin
+ * infrastructure (collector, front end), we need to store the Span information in a zipkin specific
+ * format. This class transforms a HTrace:Span object to a Zipkin:Span object.
+ * <p/>
+ * This is how both Span objects are related:
+ * <table>
+ * <col width="50%"/> <col width="50%"/> <thead>
+ * <tr>
+ * <th>HTrace:Span</th>
+ * <th>Zipkin:Span</th>
+ * </tr>
+ * <thead> <tbody>
+ * <tr>
+ * <td>TraceId</td>
+ * <td>TraceId</td>
+ * </tr>
+ * <tr>
+ * <td>ParentId</td>
+ * <td>ParentId</td>
+ * </tr>
+ * <tr>
+ * <td>SpanId</td>
+ * <td>id</td>
+ * </tr>
+ * <tr>
+ * <td>Description</td>
+ * <td>Name</td>
+ * </tr>
+ * <tr>
+ * <td>startTime, stopTime</td>
+ * <td>Annotations (cs, cr, sr, ss)</td>
+ * </tr>
+ * <tr>
+ * <td>Other annotations</td>
+ * <td>Annotations</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ * <p/>
+ */
+public class HTraceToZipkinConverter {
+
+  private final int ipv4Address;
+  private final short port;
+
+
+  private static final Map<String, Integer> DEFAULT_PORTS = new HashMap<String, Integer>();
+
+  static {
+    DEFAULT_PORTS.put("hmaster", 60000);
+    DEFAULT_PORTS.put("hregionserver",  60020);
+    DEFAULT_PORTS.put("namenode", 8020);
+    DEFAULT_PORTS.put("datanode", 50010);
+  }
+
+  public HTraceToZipkinConverter(int ipv4Address, short port) {
+    this.ipv4Address = ipv4Address;
+    this.port = port;
+  }
+
+  /**
+   * Converts a given HTrace span to a Zipkin Span.
+   * <ul>
+   * <li>First set the start annotation. [CS, SR], depending whether it is a client service or not.
+   * <li>Set other id's, etc [TraceId's etc]
+   * <li>Create binary annotations based on data from HTrace Span object.
+   * <li>Set the last annotation. [SS, CR]
+   * </ul>
+   */
+  public Span convert(org.apache.htrace.Span hTraceSpan) {
+    Span zipkinSpan = new Span();
+    String serviceName = hTraceSpan.getProcessId().toLowerCase();
+    Endpoint ep = new Endpoint(ipv4Address, (short) getPort(serviceName), serviceName);
+    List<Annotation> annotationList = createZipkinAnnotations(hTraceSpan, ep);
+    List<BinaryAnnotation> binaryAnnotationList = createZipkinBinaryAnnotations(hTraceSpan, ep);
+    zipkinSpan.setTrace_id(hTraceSpan.getTraceId());
+    if (hTraceSpan.getParentId() != org.apache.htrace.Span.ROOT_SPAN_ID) {
+      zipkinSpan.setParent_id(hTraceSpan.getParentId());
+    }
+    zipkinSpan.setId(hTraceSpan.getSpanId());
+    zipkinSpan.setName(hTraceSpan.getDescription());
+    zipkinSpan.setAnnotations(annotationList);
+    zipkinSpan.setBinary_annotations(binaryAnnotationList);
+    return zipkinSpan;
+  }
+
+  /**
+   * Add annotations from the htrace Span.
+   */
+  private List<Annotation> createZipkinAnnotations(org.apache.htrace.Span hTraceSpan,
+                                                   Endpoint ep) {
+    List<Annotation> annotationList = new ArrayList<Annotation>();
+
+    // add first zipkin  annotation.
+    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.CLIENT_SEND, hTraceSpan.getStartTimeMillis(), ep, true));
+    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.SERVER_RECV, hTraceSpan.getStartTimeMillis(), ep, true));
+    // add HTrace time annotation
+    for (TimelineAnnotation ta : hTraceSpan.getTimelineAnnotations()) {
+      annotationList.add(createZipkinAnnotation(ta.getMessage(), ta.getTime(), ep, true));
+    }
+    // add last zipkin annotation
+    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.SERVER_SEND, hTraceSpan.getStopTimeMillis(), ep, false));
+    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.CLIENT_RECV, hTraceSpan.getStopTimeMillis(), ep, false));
+    return annotationList;
+  }
+
+  /**
+   * Creates a list of Annotations that are present in HTrace Span object.
+   *
+   * @return list of Annotations that could be added to Zipkin Span.
+   */
+  private List<BinaryAnnotation> createZipkinBinaryAnnotations(org.apache.htrace.Span span,
+                                                               Endpoint ep) {
+    List<BinaryAnnotation> l = new ArrayList<BinaryAnnotation>();
+    for (Map.Entry<byte[], byte[]> e : span.getKVAnnotations().entrySet()) {
+      BinaryAnnotation binaryAnn = new BinaryAnnotation();
+      binaryAnn.setAnnotation_type(AnnotationType.BYTES);
+      binaryAnn.setKey(new String(e.getKey()));
+      binaryAnn.setValue(e.getValue());
+      binaryAnn.setHost(ep);
+      l.add(binaryAnn);
+    }
+    return l;
+  }
+
+  /**
+   * Create an annotation with the correct times and endpoint.
+   *
+   * @param value       Annotation value
+   * @param time        timestamp will be extracted
+   * @param ep          the endopint this annotation will be associated with.
+   * @param sendRequest use the first or last timestamp.
+   */
+  private static Annotation createZipkinAnnotation(String value, long time,
+                                                   Endpoint ep, boolean sendRequest) {
+    Annotation annotation = new Annotation();
+    annotation.setHost(ep);
+
+    // Zipkin is in microseconds
+    if (sendRequest) {
+      annotation.setTimestamp(time * 1000);
+    } else {
+      annotation.setTimestamp(time * 1000);
+    }
+
+    annotation.setDuration(1);
+    annotation.setValue(value);
+    return annotation;
+  }
+
+  private int getPort(String serviceName) {
+    if (port != -1) {
+      return port;
+    }
+
+    Integer p = DEFAULT_PORTS.get(serviceName);
+    if (p != null) {
+      return p;
+    }
+    return 80;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/src/main/java/org/htrace/impl/ZipkinSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-zipkin/src/main/java/org/htrace/impl/ZipkinSpanReceiver.java b/htrace-zipkin/src/main/java/org/htrace/impl/ZipkinSpanReceiver.java
deleted file mode 100644
index 9bd178c..0000000
--- a/htrace-zipkin/src/main/java/org/htrace/impl/ZipkinSpanReceiver.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.impl;
-
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import com.twitter.zipkin.gen.LogEntry;
-import com.twitter.zipkin.gen.Scribe;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.thrift.protocol.TBinaryProtocol;
-import org.apache.thrift.protocol.TProtocol;
-import org.apache.thrift.protocol.TProtocolFactory;
-import org.apache.thrift.transport.TFramedTransport;
-import org.apache.thrift.transport.TIOStreamTransport;
-import org.apache.thrift.transport.TSocket;
-import org.apache.thrift.transport.TTransport;
-import org.apache.thrift.transport.TTransportException;
-import org.htrace.HTraceConfiguration;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-import org.htrace.zipkin.HTraceToZipkinConverter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Zipkin is an open source tracing library. This span receiver acts as a bridge between HTrace and
- * Zipkin, that converts HTrace Span objects into Zipkin Span objects.
- * <p/>
- * HTrace spans are queued into a blocking queue.  From there background worker threads will
- * batch the spans together and then send them through to a Zipkin collector.
- */
-public class ZipkinSpanReceiver implements SpanReceiver {
-  private static final Log LOG = LogFactory.getLog(ZipkinSpanReceiver.class);
-
-  /**
-   * Default hostname to fall back on.
-   */
-  private static final String DEFAULT_COLLECTOR_HOSTNAME = "localhost";
-
-  /**
-   * Default collector port.
-   */
-  private static final int DEFAULT_COLLECTOR_PORT = 9410; // trace collector default port.
-
-  /**
-   * this is used to tell scribe that the entries are for zipkin..
-   */
-  private static final String CATEGORY = "zipkin";
-
-  /**
-   * Whether the service which is traced is in client or a server mode. It is used while creating
-   * the Endpoint.
-   */
-  private static final boolean DEFAULT_IN_CLIENT_MODE = false;
-
-  /**
-   * How long this receiver will try and wait for all threads to shutdown.
-   */
-  private static final int SHUTDOWN_TIMEOUT = 30;
-
-  /**
-   * How many spans this receiver will try and send in one batch.
-   */
-  private static final int MAX_SPAN_BATCH_SIZE = 100;
-
-  /**
-   * How many errors in a row before we start dropping traces on the floor.
-   */
-  private static final int MAX_ERRORS = 10;
-
-  /**
-   * The queue that will get all HTrace spans that are to be sent.
-   */
-  private final BlockingQueue<Span> queue;
-
-  /**
-   * Factory used to encode a Zipkin Span to bytes.
-   */
-  private final TProtocolFactory protocolFactory;
-
-  /**
-   * Boolean used to signal that the threads should end.
-   */
-  private final AtomicBoolean running = new AtomicBoolean(true);
-
-  /**
-   * The thread factory used to create new ExecutorService.
-   * <p/>
-   * This will be the same factory for the lifetime of this object so that
-   * no thread names will ever be duplicated.
-   */
-  private final ThreadFactory tf;
-
-  ////////////////////
-  /// Variables that will change on each call to configure()
-  ///////////////////
-  private HTraceToZipkinConverter converter;
-  private ExecutorService service;
-  private HTraceConfiguration conf;
-  private String collectorHostname;
-  private int collectorPort;
-
-  public ZipkinSpanReceiver() {
-    this.queue = new ArrayBlockingQueue<Span>(1000);
-    this.protocolFactory = new TBinaryProtocol.Factory();
-
-    tf = new ThreadFactoryBuilder().setDaemon(true)
-        .setNameFormat("zipkinSpanReceiver-%d")
-        .build();
-  }
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-    this.conf = conf;
-
-    this.collectorHostname = conf.get("zipkin.collector-hostname",
-        DEFAULT_COLLECTOR_HOSTNAME);
-    this.collectorPort = conf.getInt("zipkin.collector-port",
-        DEFAULT_COLLECTOR_PORT);
-
-    // initialize the endpoint. This endpoint is used while writing the Span.
-    initConverter();
-
-    int numThreads = conf.getInt("zipkin.num-threads", 1);
-
-    // If there are already threads runnnig tear them down.
-    if (this.service != null) {
-      this.service.shutdownNow();
-      this.service = null;
-    }
-
-    this.service = Executors.newFixedThreadPool(numThreads, tf);
-
-    for (int i = 0; i < numThreads; i++) {
-      this.service.submit(new WriteSpanRunnable());
-    }
-  }
-
-  /**
-   * Set up the HTrace to Zipkin converter.
-   */
-  private void initConverter() {
-    InetAddress tracedServiceHostname = null;
-    // Try and get the hostname.  If it's not configured try and get the local hostname.
-    try {
-      String host = conf.get("zipkin.traced-service-hostname",
-          InetAddress.getLocalHost().getHostAddress());
-
-      tracedServiceHostname = InetAddress.getByName(host);
-    } catch (UnknownHostException e) {
-      LOG.error("Couldn't get the localHost address", e);
-    }
-    short tracedServicePort = (short) conf.getInt("zipkin.traced-service-port", -1);
-    byte[] address = tracedServiceHostname != null
-        ? tracedServiceHostname.getAddress() : DEFAULT_COLLECTOR_HOSTNAME.getBytes();
-    int ipv4 = ByteBuffer.wrap(address).getInt();
-    this.converter = new HTraceToZipkinConverter(ipv4, tracedServicePort);
-  }
-
-
-  private class WriteSpanRunnable implements Runnable {
-    /**
-     * scribe client to push zipkin spans
-     */
-    private Scribe.Client scribeClient = null;
-    private final ByteArrayOutputStream baos;
-    private final TProtocol streamProtocol;
-
-    public WriteSpanRunnable() {
-      baos = new ByteArrayOutputStream();
-      streamProtocol = protocolFactory.getProtocol(new TIOStreamTransport(baos));
-    }
-
-    /**
-     * This runnable converts a HTrace span to a Zipkin span and sends it across the zipkin
-     * collector as a thrift object. The scribe client which is used for rpc writes a list of
-     * LogEntry objects, so the span objects are first transformed into LogEntry objects before
-     * sending to the zipkin-collector.
-     * <p/>
-     * Here is a little ascii art which shows the above transformation:
-     * <pre>
-     *  +------------+   +------------+   +------------+              +-----------------+
-     *  | HTrace Span|-->|Zipkin Span |-->| (LogEntry) | ===========> | Zipkin Collector|
-     *  +------------+   +------------+   +------------+ (Scribe rpc) +-----------------+
-     *  </pre>
-     */
-    @Override
-    public void run() {
-
-      List<Span> dequeuedSpans = new ArrayList<Span>(MAX_SPAN_BATCH_SIZE);
-
-      long errorCount = 0;
-
-      while (running.get() || queue.size() > 0) {
-        Span firstSpan = null;
-        try {
-          // Block for up to a second. to try and get a span.
-          // We only block for a little bit in order to notice if the running value has changed
-          firstSpan = queue.poll(1, TimeUnit.SECONDS);
-
-          // If the poll was successful then it's possible that there
-          // will be other spans to get. Try and get them.
-          if (firstSpan != null) {
-            // Add the first one that we got
-            dequeuedSpans.add(firstSpan);
-            // Try and get up to 100 queues
-            queue.drainTo(dequeuedSpans, MAX_SPAN_BATCH_SIZE - 1);
-          }
-
-        } catch (InterruptedException ie) {
-          // Ignored.
-        }
-
-        if (dequeuedSpans.isEmpty()) continue;
-
-        // If this is the first time through or there was an error re-connect
-        if (scribeClient == null) {
-          startClient();
-        }
-        // Create a new list every time through so that the list doesn't change underneath
-        // thrift as it's sending.
-        List<LogEntry> entries = new ArrayList<LogEntry>(dequeuedSpans.size());
-        try {
-          // Convert every de-queued span
-          for (Span htraceSpan : dequeuedSpans) {
-            // convert the HTrace span to Zipkin span
-            com.twitter.zipkin.gen.Span zipkinSpan = converter.convert(htraceSpan);
-            // Clear any old data.
-            baos.reset();
-            // Write the span to a BAOS
-            zipkinSpan.write(streamProtocol);
-
-            // Do Base64 encoding and put the string into a log entry.
-            LogEntry logEntry =
-                new LogEntry(CATEGORY, Base64.encodeBase64String(baos.toByteArray()));
-            entries.add(logEntry);
-          }
-
-          // Send the entries
-          scribeClient.Log(entries);
-          // clear the list for the next time through.
-          dequeuedSpans.clear();
-          // reset the error counter.
-          errorCount = 0;
-        } catch (Exception e) {
-          LOG.error("Error when writing to the zipkin collector: " +
-              collectorHostname + ":" + collectorPort, e);
-
-          errorCount += 1;
-          // If there have been ten errors in a row start dropping things.
-          if (errorCount < MAX_ERRORS) {
-            try {
-              queue.addAll(dequeuedSpans);
-            } catch (IllegalStateException ex) {
-              LOG.error("Drop " + dequeuedSpans.size() + " span(s) because queue is full");
-            }
-          }
-
-          closeClient();
-          try {
-            // Since there was an error sleep just a little bit to try and allow the
-            // zipkin collector some time to recover.
-            Thread.sleep(500);
-          } catch (InterruptedException e1) {
-            // Ignored
-          }
-        }
-      }
-      closeClient();
-    }
-
-    /**
-     * Close out the connection.
-     */
-    private void closeClient() {
-      // close out the transport.
-      if (scribeClient != null) {
-        scribeClient.getInputProtocol().getTransport().close();
-        scribeClient = null;
-      }
-    }
-
-    /**
-     * Re-connect to Zipkin.
-     */
-    private void startClient() {
-      if (this.scribeClient == null) {
-        TTransport transport = new TFramedTransport(new TSocket(collectorHostname, collectorPort));
-        try {
-          transport.open();
-        } catch (TTransportException e) {
-          e.printStackTrace();
-        }
-        TProtocol protocol = protocolFactory.getProtocol(transport);
-        this.scribeClient = new Scribe.Client(protocol);
-      }
-    }
-  }
-
-  /**
-   * Close the receiver.
-   * <p/>
-   * This tries to shut
-   *
-   * @throws IOException
-   */
-  @Override
-  public void close() throws IOException {
-    running.set(false);
-    service.shutdown();
-    try {
-      if (!service.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
-        LOG.error("Was not able to process all remaining spans to write upon closing in: " +
-            SHUTDOWN_TIMEOUT + " " + TimeUnit.SECONDS + ". There could be un-sent spans still left." +
-            "  They have been dropped.");
-      }
-    } catch (InterruptedException e1) {
-      LOG.warn("Thread interrupted when terminating executor.", e1);
-    }
-  }
-
-  @Override
-  public void receiveSpan(Span span) {
-    if (running.get()) {
-      try {
-        this.queue.add(span);
-      } catch (IllegalStateException e) {
-        LOG.error("Error trying to append span (" + span.getDescription() + ") to the queue."
-            + "  Blocking Queue was full.");
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-zipkin/src/main/java/org/htrace/zipkin/HTraceToZipkinConverter.java
----------------------------------------------------------------------
diff --git a/htrace-zipkin/src/main/java/org/htrace/zipkin/HTraceToZipkinConverter.java b/htrace-zipkin/src/main/java/org/htrace/zipkin/HTraceToZipkinConverter.java
deleted file mode 100644
index 0a3a60a..0000000
--- a/htrace-zipkin/src/main/java/org/htrace/zipkin/HTraceToZipkinConverter.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.zipkin;
-
-import com.twitter.zipkin.gen.Annotation;
-import com.twitter.zipkin.gen.AnnotationType;
-import com.twitter.zipkin.gen.BinaryAnnotation;
-import com.twitter.zipkin.gen.Endpoint;
-import com.twitter.zipkin.gen.Span;
-import com.twitter.zipkin.gen.zipkinCoreConstants;
-import org.htrace.TimelineAnnotation;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class is responsible for converting a HTrace.Span to a Zipkin.Span object. To use the Zipkin
- * infrastructure (collector, front end), we need to store the Span information in a zipkin specific
- * format. This class transforms a HTrace:Span object to a Zipkin:Span object.
- * <p/>
- * This is how both Span objects are related:
- * <table>
- * <col width="50%"/> <col width="50%"/> <thead>
- * <tr>
- * <th>HTrace:Span</th>
- * <th>Zipkin:Span</th>
- * </tr>
- * <thead> <tbody>
- * <tr>
- * <td>TraceId</td>
- * <td>TraceId</td>
- * </tr>
- * <tr>
- * <td>ParentId</td>
- * <td>ParentId</td>
- * </tr>
- * <tr>
- * <td>SpanId</td>
- * <td>id</td>
- * </tr>
- * <tr>
- * <td>Description</td>
- * <td>Name</td>
- * </tr>
- * <tr>
- * <td>startTime, stopTime</td>
- * <td>Annotations (cs, cr, sr, ss)</td>
- * </tr>
- * <tr>
- * <td>Other annotations</td>
- * <td>Annotations</td>
- * </tr>
- * </tbody>
- * </table>
- * <p/>
- */
-public class HTraceToZipkinConverter {
-
-  private final int ipv4Address;
-  private final short port;
-
-
-  private static final Map<String, Integer> DEFAULT_PORTS = new HashMap<String, Integer>();
-
-  static {
-    DEFAULT_PORTS.put("hmaster", 60000);
-    DEFAULT_PORTS.put("hregionserver",  60020);
-    DEFAULT_PORTS.put("namenode", 8020);
-    DEFAULT_PORTS.put("datanode", 50010);
-  }
-
-  public HTraceToZipkinConverter(int ipv4Address, short port) {
-    this.ipv4Address = ipv4Address;
-    this.port = port;
-  }
-
-  /**
-   * Converts a given HTrace span to a Zipkin Span.
-   * <ul>
-   * <li>First set the start annotation. [CS, SR], depending whether it is a client service or not.
-   * <li>Set other id's, etc [TraceId's etc]
-   * <li>Create binary annotations based on data from HTrace Span object.
-   * <li>Set the last annotation. [SS, CR]
-   * </ul>
-   */
-  public Span convert(org.htrace.Span hTraceSpan) {
-    Span zipkinSpan = new Span();
-    String serviceName = hTraceSpan.getProcessId().toLowerCase();
-    Endpoint ep = new Endpoint(ipv4Address, (short) getPort(serviceName), serviceName);
-    List<Annotation> annotationList = createZipkinAnnotations(hTraceSpan, ep);
-    List<BinaryAnnotation> binaryAnnotationList = createZipkinBinaryAnnotations(hTraceSpan, ep);
-    zipkinSpan.setTrace_id(hTraceSpan.getTraceId());
-    if (hTraceSpan.getParentId() != org.htrace.Span.ROOT_SPAN_ID) {
-      zipkinSpan.setParent_id(hTraceSpan.getParentId());
-    }
-    zipkinSpan.setId(hTraceSpan.getSpanId());
-    zipkinSpan.setName(hTraceSpan.getDescription());
-    zipkinSpan.setAnnotations(annotationList);
-    zipkinSpan.setBinary_annotations(binaryAnnotationList);
-    return zipkinSpan;
-  }
-
-  /**
-   * Add annotations from the htrace Span.
-   */
-  private List<Annotation> createZipkinAnnotations(org.htrace.Span hTraceSpan,
-                                                   Endpoint ep) {
-    List<Annotation> annotationList = new ArrayList<Annotation>();
-
-    // add first zipkin  annotation.
-    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.CLIENT_SEND, hTraceSpan.getStartTimeMillis(), ep, true));
-    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.SERVER_RECV, hTraceSpan.getStartTimeMillis(), ep, true));
-    // add HTrace time annotation
-    for (TimelineAnnotation ta : hTraceSpan.getTimelineAnnotations()) {
-      annotationList.add(createZipkinAnnotation(ta.getMessage(), ta.getTime(), ep, true));
-    }
-    // add last zipkin annotation
-    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.SERVER_SEND, hTraceSpan.getStopTimeMillis(), ep, false));
-    annotationList.add(createZipkinAnnotation(zipkinCoreConstants.CLIENT_RECV, hTraceSpan.getStopTimeMillis(), ep, false));
-    return annotationList;
-  }
-
-  /**
-   * Creates a list of Annotations that are present in HTrace Span object.
-   *
-   * @return list of Annotations that could be added to Zipkin Span.
-   */
-  private List<BinaryAnnotation> createZipkinBinaryAnnotations(org.htrace.Span span,
-                                                               Endpoint ep) {
-    List<BinaryAnnotation> l = new ArrayList<BinaryAnnotation>();
-    for (Map.Entry<byte[], byte[]> e : span.getKVAnnotations().entrySet()) {
-      BinaryAnnotation binaryAnn = new BinaryAnnotation();
-      binaryAnn.setAnnotation_type(AnnotationType.BYTES);
-      binaryAnn.setKey(new String(e.getKey()));
-      binaryAnn.setValue(e.getValue());
-      binaryAnn.setHost(ep);
-      l.add(binaryAnn);
-    }
-    return l;
-  }
-
-  /**
-   * Create an annotation with the correct times and endpoint.
-   *
-   * @param value       Annotation value
-   * @param time        timestamp will be extracted
-   * @param ep          the endopint this annotation will be associated with.
-   * @param sendRequest use the first or last timestamp.
-   */
-  private static Annotation createZipkinAnnotation(String value, long time,
-                                                   Endpoint ep, boolean sendRequest) {
-    Annotation annotation = new Annotation();
-    annotation.setHost(ep);
-
-    // Zipkin is in microseconds
-    if (sendRequest) {
-      annotation.setTimestamp(time * 1000);
-    } else {
-      annotation.setTimestamp(time * 1000);
-    }
-
-    annotation.setDuration(1);
-    annotation.setValue(value);
-    return annotation;
-  }
-
-  private int getPort(String serviceName) {
-    if (port != -1) {
-      return port;
-    }
-
-    Integer p = DEFAULT_PORTS.get(serviceName);
-    if (p != null) {
-      return p;
-    }
-    return 80;
-  }
-}


[7/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/TimelineAnnotation.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/TimelineAnnotation.java b/htrace-core/src/main/java/org/htrace/TimelineAnnotation.java
deleted file mode 100644
index 265d209..0000000
--- a/htrace-core/src/main/java/org/htrace/TimelineAnnotation.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-public class TimelineAnnotation {
-  private final long time;
-  private final String msg;
-
-  public TimelineAnnotation(long time, String msg) {
-    this.time = time;
-    this.msg = msg;
-  }
-
-  public long getTime() {
-    return time;
-  }
-
-  public String getMessage() {
-    return msg;
-  }
-
-  @Override
-  public String toString() {
-    return "@" + time + ": " + msg;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/Trace.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/Trace.java b/htrace-core/src/main/java/org/htrace/Trace.java
deleted file mode 100644
index 8b1255b..0000000
--- a/htrace-core/src/main/java/org/htrace/Trace.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import org.htrace.impl.MilliSpan;
-import org.htrace.impl.TrueIfTracingSampler;
-import org.htrace.wrappers.TraceCallable;
-import org.htrace.wrappers.TraceRunnable;
-
-import java.security.SecureRandom;
-import java.util.Random;
-import java.util.concurrent.Callable;
-
-/**
- * The primary way to interact with the library. Provides methods to start
- * spans, as well as set necessary tracing information.
- */
-public class Trace {
-  private final static Random random = new SecureRandom();
-
-  /**
-   * Starts and returns a new span as the child of the current span if the
-   * default sampler (TrueIfTracingSampler) returns true, otherwise returns the
-   * NullSpan.
-   *
-   * @param description Description of the span to be created.
-   * @return
-   */
-  public static TraceScope startSpan(String description) {
-    return startSpan(description, TrueIfTracingSampler.INSTANCE);
-  }
-
-  /**
-   * Starts and returns a new span as the child of the parameter 'parent'. This
-   * will always return a new span, even if tracing wasn't previously enabled for
-   * this thread.
-   *
-   * @param description Description of the span to be created.
-   * @param parent      The parent that should be used to create the child span that is to
-   *                    be returned.
-   * @return
-   */
-  public static TraceScope startSpan(String description, Span parent) {
-    if (parent == null) return startSpan(description);
-    return continueSpan(parent.child(description));
-  }
-
-  public static TraceScope startSpan(String description, TraceInfo tinfo) {
-    if (tinfo == null) return continueSpan(null);
-    Span newSpan = new MilliSpan(description, tinfo.traceId, tinfo.spanId,
-        random.nextLong(), Tracer.getProcessId());
-    return continueSpan(newSpan);
-  }
-
-  public static <T> TraceScope startSpan(String description, Sampler<T> s) {
-    return startSpan(description, s, null);
-  }
-
-  public static TraceScope startSpan(String description, Sampler<TraceInfo> s, TraceInfo tinfo) {
-    Span span = null;
-    if (isTracing() || s.next(tinfo)) {
-      span = new MilliSpan(description, tinfo.traceId, tinfo.spanId,
-          random.nextLong(), Tracer.getProcessId());
-    }
-    return continueSpan(span);
-  }
-
-  public static <T> TraceScope startSpan(String description, Sampler<T> s, T info) {
-    Span span = null;
-    if (isTracing() || s.next(info)) {
-      span = Tracer.getInstance().createNew(description);
-    }
-    return continueSpan(span);
-  }
-
-  /**
-   * Pick up an existing span from another thread.
-   */
-  public static TraceScope continueSpan(Span s) {
-    // Return an empty TraceScope that does nothing on close
-    if (s == null) return NullScope.INSTANCE;
-    return Tracer.getInstance().continueSpan(s);
-  }
-
-  /**
-   * Set the processId to be used for all Spans created by this Tracer.
-   *
-   * @param processId
-   * @see Span.java
-   */
-  public static void setProcessId(String processId) {
-    Tracer.processId = processId;
-  }
-
-  /**
-   * Removes the given SpanReceiver from the list of SpanReceivers.
-   *
-   * @param rcvr
-   */
-  public static void removeReceiver(SpanReceiver rcvr) {
-    Tracer.getInstance().removeReceiver(rcvr);
-  }
-
-  /**
-   * Adds the given SpanReceiver to the current Tracer instance's list of
-   * SpanReceivers.
-   *
-   * @param rcvr
-   */
-  public static void addReceiver(SpanReceiver rcvr) {
-    Tracer.getInstance().addReceiver(rcvr);
-  }
-
-  /**
-   * Adds a data annotation to the current span if tracing is currently on.
-   */
-  public static void addKVAnnotation(byte[] key, byte[] value) {
-    Span s = currentSpan();
-    if (s != null) {
-      s.addKVAnnotation(key, value);
-    }
-  }
-
-  /**
-   * Annotate the current span with the given message.
-   */
-  public static void addTimelineAnnotation(String msg) {
-    Span s = currentSpan();
-    if (s != null) {
-      s.addTimelineAnnotation(msg);
-    }
-  }
-
-  /**
-   * Returns true if the current thread is a part of a trace, false otherwise.
-   *
-   * @return
-   */
-  public static boolean isTracing() {
-    return Tracer.getInstance().isTracing();
-  }
-
-  /**
-   * If we are tracing, return the current span, else null
-   *
-   * @return Span representing the current trace, or null if not tracing.
-   */
-  public static Span currentSpan() {
-    return Tracer.getInstance().currentSpan();
-  }
-
-  /**
-   * Wrap the callable in a TraceCallable, if tracing.
-   *
-   * @param callable
-   * @return The callable provided, wrapped if tracing, 'callable' if not.
-   */
-  public static <V> Callable<V> wrap(Callable<V> callable) {
-    if (isTracing()) {
-      return new TraceCallable<V>(Trace.currentSpan(), callable);
-    } else {
-      return callable;
-    }
-  }
-
-  /**
-   * Wrap the runnable in a TraceRunnable, if tracing
-   *
-   * @param runnable
-   * @return The runnable provided, wrapped if tracing, 'runnable' if not.
-   */
-  public static Runnable wrap(Runnable runnable) {
-    if (isTracing()) {
-      return new TraceRunnable(Trace.currentSpan(), runnable);
-    } else {
-      return runnable;
-    }
-  }
-
-  /**
-   * Wrap the runnable in a TraceRunnable, if tracing
-   *
-   * @param description name of the span to be created.
-   * @param runnable
-   * @return The runnable provided, wrapped if tracing, 'runnable' if not.
-   */
-  public static Runnable wrap(String description, Runnable runnable) {
-    if (isTracing()) {
-      return new TraceRunnable(Trace.currentSpan(), runnable, description);
-    } else {
-      return runnable;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/TraceInfo.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/TraceInfo.java b/htrace-core/src/main/java/org/htrace/TraceInfo.java
deleted file mode 100644
index 438289d..0000000
--- a/htrace-core/src/main/java/org/htrace/TraceInfo.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-
-public class TraceInfo {
-  public final long traceId;
-  public final long spanId;
-
-  public TraceInfo(long traceId, long spanId) {
-    this.traceId = traceId;
-    this.spanId = spanId;
-  }
-
-  @Override
-  public String toString() {
-    return "TraceInfo(traceId=" + traceId + ", spanId=" + spanId + ")";
-  }
-
-  public static TraceInfo fromSpan(Span s) {
-    if (s == null) return null;
-    return new TraceInfo(s.getTraceId(), s.getSpanId());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/TraceScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/TraceScope.java b/htrace-core/src/main/java/org/htrace/TraceScope.java
deleted file mode 100644
index f001c52..0000000
--- a/htrace-core/src/main/java/org/htrace/TraceScope.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import java.io.Closeable;
-
-public class TraceScope implements Closeable {
-
-  /**
-   * the span for this scope
-   */
-  private final Span span;
-
-  /**
-   * the span that was "current" before this scope was entered
-   */
-  private final Span savedSpan;
-
-  private boolean detached = false;
-
-  TraceScope(Span span, Span saved) {
-    this.span = span;
-    this.savedSpan = saved;
-  }
-
-  public Span getSpan() {
-    return span;
-  }
-
-  /**
-   * Remove this span as the current thread, but don't stop it yet or
-   * send it for collection. This is useful if the span object is then
-   * passed to another thread for use with Trace.continueTrace().
-   *
-   * @return the same Span object
-   */
-  public Span detach() {
-    detached = true;
-
-    Span cur = Tracer.getInstance().currentSpan();
-    if (cur != span) {
-      Tracer.LOG.debug("Closing trace span " + span + " but " +
-          cur + " was top-of-stack");
-    } else {
-      Tracer.getInstance().setCurrentSpan(savedSpan);
-    }
-    return span;
-  }
-
-  /**
-   * Return true when {@link #detach()} has been called. Helpful when debugging
-   * multiple threads working on a single span.
-   */
-  public boolean isDetached() {
-    return detached;
-  }
-
-  @Override
-  public void close() {
-    if (span == null) return;
-
-    if (!detached) {
-      // The span is done
-      span.stop();
-      detach();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/TraceTree.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/TraceTree.java b/htrace-core/src/main/java/org/htrace/TraceTree.java
deleted file mode 100644
index fadcf2f..0000000
--- a/htrace-core/src/main/java/org/htrace/TraceTree.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Multimap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.Collection;
-
-/**
- * Used to create the graph formed by spans.
- */
-public class TraceTree {
-  public static final Log LOG = LogFactory.getLog(Tracer.class);
-  private Multimap<Long, Span> spansByParentID;
-  private Collection<Span> spans;
-  private Multimap<String, Span> spansByPid;
-
-  /**
-   * Create a new TraceTree
-   *
-   * @param spans The collection of spans to use to create this TraceTree. Should
-   *              have at least one root span (span with parentId =
-   *              Span.ROOT_SPAN_ID
-   */
-  public TraceTree(Collection<Span> spans) {
-    this.spans = ImmutableList.copyOf(spans);
-    this.spansByParentID = HashMultimap.<Long, Span>create();
-    this.spansByPid = HashMultimap.<String, Span>create();
-
-    for (Span s : this.spans) {
-      if (s.getProcessId() != null) {
-        spansByPid.put(s.getProcessId(), s);
-      } else {
-        LOG.warn("Encountered span with null processId. This should not happen. Span: "
-            + s);
-      }
-      spansByParentID.put(s.getParentId(), s);
-    }
-  }
-
-  /**
-   * @return The collection of spans given to this TraceTree at construction.
-   */
-  public Collection<Span> getSpans() {
-    return spans;
-  }
-
-  /**
-   * @return A copy of the MultiMap from parent span ID -> children of span with
-   *         that ID.
-   */
-  public Multimap<Long, Span> getSpansByParentIdMap() {
-    return HashMultimap.<Long, Span>create(spansByParentID);
-  }
-
-  /**
-   * @return A collection of the root spans (spans with parent ID =
-   *         Span.ROOT_SPAN_ID) in this tree.
-   */
-  public Collection<Span> getRoots() {
-    Collection<Span> roots = spansByParentID.get(Span.ROOT_SPAN_ID);
-    if (roots != null) {
-      return roots;
-    }
-    throw new IllegalStateException(
-        "TraceTree is not correctly formed - there are no root spans in the collection provided at construction.");
-  }
-
-  /**
-   * @return A copy of the Multimap from String process ID -> spans with that
-   *         process ID. If process ID was not set in Trace.java, all spans will
-   *         have empty string process IDs.
-   */
-  public Multimap<String, Span> getSpansByPidMap() {
-    return HashMultimap.<String, Span>create(spansByPid);
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/Tracer.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/Tracer.java b/htrace-core/src/main/java/org/htrace/Tracer.java
deleted file mode 100644
index ac31165..0000000
--- a/htrace-core/src/main/java/org/htrace/Tracer.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.htrace.impl.MilliSpan;
-
-import java.security.SecureRandom;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * A Tracer provides the implementation for collecting and distributing Spans
- * within a process.
- */
-public class Tracer {
-  public static final Log LOG = LogFactory.getLog(Tracer.class);
-  private final static Random random = new SecureRandom();
-  private final List<SpanReceiver> receivers = new CopyOnWriteArrayList<SpanReceiver>();
-  private static final ThreadLocal<Span> currentSpan = new ThreadLocal<Span>() {
-    @Override
-    protected Span initialValue() {
-      return null;
-    }
-  };
-  public static final TraceInfo DONT_TRACE = new TraceInfo(-1, -1);
-  protected static String processId = null;
-
-  /**
-   * Internal class for defered singleton idiom.
-   * <p/>
-   * https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
-   */
-  private static class TracerHolder {
-    private static final Tracer INSTANCE = new Tracer();
-  }
-
-  public static Tracer getInstance() {
-    return TracerHolder.INSTANCE;
-  }
-
-  protected Span createNew(String description) {
-    Span parent = currentSpan.get();
-    if (parent == null) {
-      return new MilliSpan(description,
-          /* traceId = */ random.nextLong(),
-          /* parentSpanId = */ Span.ROOT_SPAN_ID,
-          /* spanId = */ random.nextLong(),
-          getProcessId());
-    } else {
-      return parent.child(description);
-    }
-  }
-
-  protected boolean isTracing() {
-    return currentSpan.get() != null;
-  }
-
-  protected Span currentSpan() {
-    return currentSpan.get();
-  }
-
-  public void deliver(Span span) {
-    for (SpanReceiver receiver : receivers) {
-      receiver.receiveSpan(span);
-    }
-  }
-
-  protected void addReceiver(SpanReceiver receiver) {
-    receivers.add(receiver);
-  }
-
-  protected void removeReceiver(SpanReceiver receiver) {
-    receivers.remove(receiver);
-  }
-
-  protected Span setCurrentSpan(Span span) {
-    if (LOG.isTraceEnabled()) {
-      LOG.trace("setting current span " + span);
-    }
-    currentSpan.set(span);
-    return span;
-  }
-
-
-  public TraceScope continueSpan(Span s) {
-    Span oldCurrent = currentSpan();
-    setCurrentSpan(s);
-    return new TraceScope(s, oldCurrent);
-  }
-
-  protected int numReceivers() {
-    return receivers.size();
-  }
-
-  static String getProcessId() {
-    if (processId == null) {
-      String cmdLine = System.getProperty("sun.java.command");
-      if (cmdLine != null && !cmdLine.isEmpty()) {
-        String fullClassName = cmdLine.split("\\s+")[0];
-        String[] classParts = fullClassName.split("\\.");
-        cmdLine = classParts[classParts.length - 1];
-      }
-
-      processId = (cmdLine == null || cmdLine.isEmpty()) ? "Unknown" : cmdLine;
-    }
-    return processId;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/AlwaysSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/AlwaysSampler.java b/htrace-core/src/main/java/org/htrace/impl/AlwaysSampler.java
deleted file mode 100644
index c8d53e8..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/AlwaysSampler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.Sampler;
-
-public final class AlwaysSampler implements Sampler<Object> {
-
-  public static final AlwaysSampler INSTANCE = new AlwaysSampler();
-
-  private AlwaysSampler() {
-  }
-
-  @Override
-  public boolean next(Object info) {
-    return true;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/CountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/CountSampler.java b/htrace-core/src/main/java/org/htrace/impl/CountSampler.java
deleted file mode 100644
index 8afcd8e..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/CountSampler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.Sampler;
-
-import java.util.Random;
-
-/**
- * Sampler that returns true every N calls.
- */
-public class CountSampler implements Sampler<Object> {
-
-  final static Random random = new Random();
-
-  final long frequency;
-  long count = random.nextLong();
-
-  public CountSampler(long frequency) {
-    this.frequency = frequency;
-  }
-
-  @Override
-  public boolean next(Object info) {
-    return (count++ % frequency) == 0;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/LocalFileSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/LocalFileSpanReceiver.java b/htrace-core/src/main/java/org/htrace/impl/LocalFileSpanReceiver.java
deleted file mode 100644
index b05b067..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/LocalFileSpanReceiver.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.htrace.HTraceConfiguration;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-import org.mortbay.util.ajax.JSON;
-
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Writes the spans it receives to a local file.
- * A production LocalFileSpanReceiver should use a real CSV format.
- */
-public class LocalFileSpanReceiver implements SpanReceiver {
-  public static final Log LOG = LogFactory.getLog(LocalFileSpanReceiver.class);
-  public static final String PATH_KEY = "local-file-span-receiver.path";
-  public static final String CAPACITY_KEY = "local-file-span-receiver.capacity";
-  // default capacity for the executors blocking queue
-  public static final int CAPACITY_DEFAULT = 5000;
-  // default timeout duration when calling executor.awaitTermination()
-  public static final long EXECUTOR_TERMINATION_TIMEOUT_DURATION_DEFAULT = 60;
-  private String file;
-  private FileWriter fwriter;
-  private BufferedWriter bwriter;
-  private Map<String, Object> values;
-  private ExecutorService executor;
-  private long executorTerminationTimeoutDuration;
-
-  public LocalFileSpanReceiver() {
-  }
-
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-    this.executorTerminationTimeoutDuration = EXECUTOR_TERMINATION_TIMEOUT_DURATION_DEFAULT;
-    int capacity = conf.getInt(CAPACITY_KEY, CAPACITY_DEFAULT);
-    this.file = conf.get(PATH_KEY);
-    if (file == null || file.isEmpty()) {
-      throw new IllegalArgumentException("must configure " + PATH_KEY);
-    }
-    this.executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS,
-        new LinkedBlockingQueue<Runnable>(capacity));
-    try {
-      this.fwriter = new FileWriter(this.file, true);
-    } catch (IOException ioe) {
-      throw new RuntimeException(ioe);
-    }
-    this.bwriter = new BufferedWriter(fwriter);
-    this.values = new LinkedHashMap<String, Object>();
-  }
-
-
-  private class WriteSpanRunnable implements Runnable {
-    public final Span span;
-
-    public WriteSpanRunnable(Span span) {
-      this.span = span;
-    }
-
-    @Override
-    public void run() {
-      try {
-        values.put("TraceID", span.getTraceId());
-        values.put("SpanID", span.getSpanId());
-        values.put("ParentID", span.getParentId());
-        values.put("ProcessID", span.getProcessId());
-        values.put("Start", span.getStartTimeMillis());
-        values.put("Stop", span.getStopTimeMillis());
-        values.put("Description", span.getDescription());
-        values.put("KVAnnotations", span.getKVAnnotations());
-        values.put("TLAnnotations", span.getTimelineAnnotations());
-        bwriter.write(JSON.toString(values));
-        bwriter.newLine();
-        bwriter.flush();
-        values.clear();
-      } catch (IOException e) {
-        LOG.error("Error when writing to file: " + file, e);
-      }
-    }
-  }
-
-  @Override
-  public void receiveSpan(Span span) {
-    executor.submit(new WriteSpanRunnable(span));
-  }
-
-  @Override
-  public void close() throws IOException {
-    executor.shutdown();
-    try {
-      if (!executor.awaitTermination(this.executorTerminationTimeoutDuration,
-          TimeUnit.SECONDS)) {
-        LOG.warn("Was not able to process all remaining spans to write upon closing in: "
-            + this.executorTerminationTimeoutDuration + "s");
-      }
-    } catch (InterruptedException e1) {
-      LOG.warn("Thread interrupted when terminating executor.", e1);
-    }
-
-    try {
-      fwriter.close();
-    } catch (IOException e) {
-      LOG.error("Error closing filewriter for file: " + file, e);
-    }
-    try {
-      bwriter.close();
-    } catch (IOException e) {
-      LOG.error("Error closing bufferedwriter for file: " + file, e);
-    }
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/MilliSpan.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/MilliSpan.java b/htrace-core/src/main/java/org/htrace/impl/MilliSpan.java
deleted file mode 100644
index 39c9671..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/MilliSpan.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.Span;
-import org.htrace.TimelineAnnotation;
-import org.htrace.Tracer;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-/**
- * A Span implementation that stores its information in milliseconds since the
- * epoch.
- */
-public class MilliSpan implements Span {
-
-  private static Random rand = new Random();
-
-  private long start;
-  private long stop;
-  private final String description;
-  private final long traceId;
-  private final long parentSpanId;
-  private final long spanId;
-  private Map<byte[], byte[]> traceInfo = null;
-  private final String processId;
-  private List<TimelineAnnotation> timeline = null;
-
-  @Override
-  public Span child(String description) {
-    return new MilliSpan(description, traceId, spanId, rand.nextLong(), processId);
-  }
-
-  public MilliSpan(String description, long traceId, long parentSpanId, long spanId, String processId) {
-    this.description = description;
-    this.traceId = traceId;
-    this.parentSpanId = parentSpanId;
-    this.spanId = spanId;
-    this.start = System.currentTimeMillis();
-    this.stop = 0;
-    this.processId = processId;
-  }
-
-  @Override
-  public synchronized void stop() {
-    if (stop == 0) {
-      if (start == 0)
-        throw new IllegalStateException("Span for " + description
-            + " has not been started");
-      stop = System.currentTimeMillis();
-      Tracer.getInstance().deliver(this);
-    }
-  }
-
-  protected long currentTimeMillis() {
-    return System.currentTimeMillis();
-  }
-
-  @Override
-  public synchronized boolean isRunning() {
-    return start != 0 && stop == 0;
-  }
-
-  @Override
-  public synchronized long getAccumulatedMillis() {
-    if (start == 0)
-      return 0;
-    if (stop > 0)
-      return stop - start;
-    return currentTimeMillis() - start;
-  }
-
-  @Override
-  public String toString() {
-    return String.format("Span{Id:0x%16x,parentId:0x%16x,desc:%s}", spanId, parentSpanId, description);
-  }
-
-  @Override
-  public String getDescription() {
-    return description;
-  }
-
-  @Override
-  public long getSpanId() {
-    return spanId;
-  }
-
-  @Override
-  public long getParentId() {
-    return parentSpanId;
-  }
-
-  @Override
-  public long getTraceId() {
-    return traceId;
-  }
-
-  @Override
-  public long getStartTimeMillis() {
-    return start;
-  }
-
-  @Override
-  public long getStopTimeMillis() {
-    return stop;
-  }
-
-  @Override
-  public void addKVAnnotation(byte[] key, byte[] value) {
-    if (traceInfo == null)
-      traceInfo = new HashMap<byte[], byte[]>();
-    traceInfo.put(key, value);
-  }
-
-  @Override
-  public void addTimelineAnnotation(String msg) {
-    if (timeline == null) {
-      timeline = new ArrayList<TimelineAnnotation>();
-    }
-    timeline.add(new TimelineAnnotation(System.currentTimeMillis(), msg));
-  }
-
-  @Override
-  public Map<byte[], byte[]> getKVAnnotations() {
-    if (traceInfo == null)
-      return Collections.emptyMap();
-    return Collections.unmodifiableMap(traceInfo);
-  }
-
-  @Override
-  public List<TimelineAnnotation> getTimelineAnnotations() {
-    if (timeline == null) {
-      return Collections.emptyList();
-    }
-    return Collections.unmodifiableList(timeline);
-  }
-
-  @Override
-  public String getProcessId() {
-    return processId;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/NeverSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/NeverSampler.java b/htrace-core/src/main/java/org/htrace/impl/NeverSampler.java
deleted file mode 100644
index 38b193a..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/NeverSampler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.Sampler;
-
-public final class NeverSampler implements Sampler<Object> {
-
-  public static final NeverSampler INSTANCE = new NeverSampler();
-
-  private NeverSampler() {
-  }
-
-  @Override
-  public boolean next(Object info) {
-    return false;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/POJOSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/POJOSpanReceiver.java b/htrace-core/src/main/java/org/htrace/impl/POJOSpanReceiver.java
deleted file mode 100644
index 54874e6..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/POJOSpanReceiver.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.HTraceConfiguration;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashSet;
-
-/**
- * SpanReceiver for testing only that just collects the Span objects it
- * receives. The spans it receives can be accessed with getSpans();
- */
-public class POJOSpanReceiver implements SpanReceiver {
-  private final Collection<Span> spans;
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-  }
-
-  /**
-   * @return The spans this POJOSpanReceiver has received.
-   */
-  public Collection<Span> getSpans() {
-    return spans;
-  }
-
-  public POJOSpanReceiver() {
-    this.spans = new HashSet<Span>();
-  }
-
-  @Override
-  public void close() throws IOException {
-  }
-
-  @Override
-  public void receiveSpan(Span span) {
-    spans.add(span);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/ProbabilitySampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/ProbabilitySampler.java b/htrace-core/src/main/java/org/htrace/impl/ProbabilitySampler.java
deleted file mode 100644
index 1ac1f73..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/ProbabilitySampler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.Sampler;
-
-import java.util.Random;
-
-public class ProbabilitySampler implements Sampler<Object> {
-  public final double threshold;
-  private Random random;
-
-  public ProbabilitySampler(double threshold) {
-    this.threshold = threshold;
-    random = new Random();
-  }
-
-  @Override
-  public boolean next(Object info) {
-    return random.nextDouble() < threshold;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/StandardOutSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/StandardOutSpanReceiver.java b/htrace-core/src/main/java/org/htrace/impl/StandardOutSpanReceiver.java
deleted file mode 100644
index f1ebada..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/StandardOutSpanReceiver.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.HTraceConfiguration;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-
-import java.io.IOException;
-
-/**
- * Used for testing. Simply prints to standard out any spans it receives.
- */
-public class StandardOutSpanReceiver implements SpanReceiver {
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-  }
-
-  @Override
-  public void receiveSpan(Span span) {
-    System.out.println(span);
-  }
-
-  @Override
-  public void close() throws IOException {
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/impl/TrueIfTracingSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/impl/TrueIfTracingSampler.java b/htrace-core/src/main/java/org/htrace/impl/TrueIfTracingSampler.java
deleted file mode 100644
index 100650e..0000000
--- a/htrace-core/src/main/java/org/htrace/impl/TrueIfTracingSampler.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.impl;
-
-import org.htrace.Sampler;
-import org.htrace.Trace;
-
-/**
- * A Sampler that returns true if and only if tracing is on the current thread.
- */
-public class TrueIfTracingSampler implements Sampler<Object> {
-
-  public static final TrueIfTracingSampler INSTANCE = new TrueIfTracingSampler();
-
-  private TrueIfTracingSampler() {
-  }
-
-  @Override
-  public boolean next(Object info) {
-    return Trace.isTracing();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/wrappers/TraceCallable.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/wrappers/TraceCallable.java b/htrace-core/src/main/java/org/htrace/wrappers/TraceCallable.java
deleted file mode 100644
index 5b25893..0000000
--- a/htrace-core/src/main/java/org/htrace/wrappers/TraceCallable.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.wrappers;
-
-import org.htrace.Span;
-import org.htrace.Trace;
-import org.htrace.TraceScope;
-
-import java.util.concurrent.Callable;
-
-/**
- * Wrap a Callable with a Span that survives a change in threads.
- */
-public class TraceCallable<V> implements Callable<V> {
-  private final Callable<V> impl;
-  private final Span parent;
-  private final String description;
-
-  public TraceCallable(Callable<V> impl) {
-    this(Trace.currentSpan(), impl);
-  }
-
-  public TraceCallable(Span parent, Callable<V> impl) {
-    this(parent, impl, null);
-  }
-
-  public TraceCallable(Span parent, Callable<V> impl, String description) {
-    this.impl = impl;
-    this.parent = parent;
-    this.description = description;
-  }
-
-  @Override
-  public V call() throws Exception {
-    if (parent != null) {
-      TraceScope chunk = Trace.startSpan(getDescription(), parent);
-
-      try {
-        return impl.call();
-      } finally {
-        chunk.close();
-      }
-    } else {
-      return impl.call();
-    }
-  }
-
-  public Callable<V> getImpl() {
-    return impl;
-  }
-
-  private String getDescription() {
-    return this.description == null ? Thread.currentThread().getName() : description;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/wrappers/TraceExecutorService.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/wrappers/TraceExecutorService.java b/htrace-core/src/main/java/org/htrace/wrappers/TraceExecutorService.java
deleted file mode 100644
index 95ae88a..0000000
--- a/htrace-core/src/main/java/org/htrace/wrappers/TraceExecutorService.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.wrappers;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-
-public class TraceExecutorService implements ExecutorService {
-
-  private final ExecutorService impl;
-
-  public TraceExecutorService(ExecutorService impl) {
-    this.impl = impl;
-  }
-
-  @Override
-  public void execute(Runnable command) {
-    impl.execute(new TraceRunnable(command));
-  }
-
-  @Override
-  public void shutdown() {
-    impl.shutdown();
-  }
-
-  @Override
-  public List<Runnable> shutdownNow() {
-    return impl.shutdownNow();
-  }
-
-  @Override
-  public boolean isShutdown() {
-    return impl.isShutdown();
-  }
-
-  @Override
-  public boolean isTerminated() {
-    return impl.isTerminated();
-  }
-
-  @Override
-  public boolean awaitTermination(long timeout, TimeUnit unit)
-      throws InterruptedException {
-    return impl.awaitTermination(timeout, unit);
-  }
-
-  @Override
-  public <T> Future<T> submit(Callable<T> task) {
-    return impl.submit(new TraceCallable<T>(task));
-  }
-
-  @Override
-  public <T> Future<T> submit(Runnable task, T result) {
-    return impl.submit(new TraceRunnable(task), result);
-  }
-
-  @Override
-  public Future<?> submit(Runnable task) {
-    return impl.submit(new TraceRunnable(task));
-  }
-
-  private <T> Collection<? extends Callable<T>> wrapCollection(
-      Collection<? extends Callable<T>> tasks) {
-    List<Callable<T>> result = new ArrayList<Callable<T>>();
-    for (Callable<T> task : tasks) {
-      result.add(new TraceCallable<T>(task));
-    }
-    return result;
-  }
-
-  @Override
-  public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
-      throws InterruptedException {
-    return impl.invokeAll(wrapCollection(tasks));
-  }
-
-  @Override
-  public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
-                                       long timeout, TimeUnit unit) throws InterruptedException {
-    return impl.invokeAll(wrapCollection(tasks), timeout, unit);
-  }
-
-  @Override
-  public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
-      throws InterruptedException, ExecutionException {
-    return impl.invokeAny(wrapCollection(tasks));
-  }
-
-  @Override
-  public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout,
-                         TimeUnit unit) throws InterruptedException, ExecutionException,
-      TimeoutException {
-    return impl.invokeAny(wrapCollection(tasks), timeout, unit);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/wrappers/TraceProxy.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/wrappers/TraceProxy.java b/htrace-core/src/main/java/org/htrace/wrappers/TraceProxy.java
deleted file mode 100644
index 42cdd5a..0000000
--- a/htrace-core/src/main/java/org/htrace/wrappers/TraceProxy.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.wrappers;
-
-import org.htrace.Sampler;
-import org.htrace.Trace;
-import org.htrace.TraceScope;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-public class TraceProxy {
-  /**
-   * Returns an object that will trace all calls to itself.
-   *
-   * @param instance
-   * @return
-   */
-  public static <T> T trace(T instance) {
-    return trace(instance, Sampler.ALWAYS);
-  }
-
-  /**
-   * Returns an object that will trace all calls to itself.
-   *
-   * @param <V>
-   * @param instance
-   * @param sampler
-   * @return
-   */
-  @SuppressWarnings("unchecked")
-  public static <T, V> T trace(final T instance, final Sampler<V> sampler) {
-    InvocationHandler handler = new InvocationHandler() {
-      @Override
-      public Object invoke(Object obj, Method method, Object[] args)
-          throws Throwable {
-        if (!sampler.next(null)) {
-          return method.invoke(instance, args);
-        }
-
-        TraceScope scope = Trace.startSpan(method.getName(), Sampler.ALWAYS);
-        try {
-          return method.invoke(instance, args);
-        } catch (Throwable ex) {
-          ex.printStackTrace();
-          throw ex;
-        } finally {
-          scope.close();
-        }
-      }
-    };
-    return (T) Proxy.newProxyInstance(instance.getClass().getClassLoader(),
-        instance.getClass().getInterfaces(), handler);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/main/java/org/htrace/wrappers/TraceRunnable.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/htrace/wrappers/TraceRunnable.java b/htrace-core/src/main/java/org/htrace/wrappers/TraceRunnable.java
deleted file mode 100644
index 9f7ea1e..0000000
--- a/htrace-core/src/main/java/org/htrace/wrappers/TraceRunnable.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace.wrappers;
-
-import org.htrace.Span;
-import org.htrace.Trace;
-import org.htrace.TraceScope;
-
-/**
- * Wrap a Runnable with a Span that survives a change in threads.
- */
-public class TraceRunnable implements Runnable {
-
-  private final Span parent;
-  private final Runnable runnable;
-  private final String description;
-
-  public TraceRunnable(Runnable runnable) {
-    this(Trace.currentSpan(), runnable);
-  }
-
-  public TraceRunnable(Span parent, Runnable runnable) {
-    this(parent, runnable, null);
-  }
-
-  public TraceRunnable(Span parent, Runnable runnable, String description) {
-    this.parent = parent;
-    this.runnable = runnable;
-    this.description = description;
-  }
-
-  @Override
-  public void run() {
-    if (parent != null) {
-      TraceScope chunk = Trace.startSpan(getDescription(), parent);
-
-      try {
-        runnable.run();
-      } finally {
-        chunk.close();
-      }
-    } else {
-      runnable.run();
-    }
-  }
-
-  private String getDescription() {
-    return this.description == null ? Thread.currentThread().getName() : description;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/apache/htrace/TestCountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/TestCountSampler.java b/htrace-core/src/test/java/org/apache/htrace/TestCountSampler.java
new file mode 100644
index 0000000..41c06a3
--- /dev/null
+++ b/htrace-core/src/test/java/org/apache/htrace/TestCountSampler.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import org.apache.htrace.impl.CountSampler;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCountSampler {
+
+  @Test
+  public void testNext() {
+    CountSampler half = new CountSampler(2);
+    CountSampler hundred = new CountSampler(100);
+    int halfCount = 0;
+    int hundredCount = 0;
+    for (int i = 0; i < 200; i++) {
+      if (half.next(null))
+        halfCount++;
+      if (hundred.next(null))
+        hundredCount++;
+    }
+    Assert.assertEquals(2, hundredCount);
+    Assert.assertEquals(100, halfCount);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/apache/htrace/TestHTrace.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/TestHTrace.java b/htrace-core/src/test/java/org/apache/htrace/TestHTrace.java
new file mode 100644
index 0000000..ebca7fb
--- /dev/null
+++ b/htrace-core/src/test/java/org/apache/htrace/TestHTrace.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import com.google.common.collect.Multimap;
+
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.TraceTree;
+import org.apache.htrace.impl.LocalFileSpanReceiver;
+import org.apache.htrace.impl.POJOSpanReceiver;
+import org.apache.htrace.impl.StandardOutSpanReceiver;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+public class TestHTrace {
+
+  public static final String SPAN_FILE_FLAG = "spanFile";
+
+  /**
+   * Basic system test of HTrace.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testHtrace() throws Exception {
+    final int numTraces = 3;
+    String fileName = System.getProperty(SPAN_FILE_FLAG);
+
+    Collection<SpanReceiver> rcvrs = new HashSet<SpanReceiver>();
+
+    // writes spans to a file if one is provided to maven with
+    // -DspanFile="FILENAME", otherwise writes to standard out.
+    if (fileName != null) {
+      File f = new File(fileName);
+      File parent = f.getParentFile();
+      if (parent != null && !parent.exists() && !parent.mkdirs()) {
+        throw new IllegalArgumentException("Couldn't create file: "
+            + fileName);
+      }
+      HashMap<String, String> conf = new HashMap<String, String>();
+      conf.put("local-file-span-receiver.path", fileName);
+      LocalFileSpanReceiver receiver = new LocalFileSpanReceiver();
+      receiver.configure(HTraceConfiguration.fromMap(conf));
+      rcvrs.add(receiver);
+    } else {
+      rcvrs.add(new StandardOutSpanReceiver());
+    }
+
+    POJOSpanReceiver psr = new POJOSpanReceiver();
+    rcvrs.add(psr);
+    runTraceCreatorTraces(new TraceCreator(rcvrs));
+
+    for (SpanReceiver receiver : rcvrs) {
+      receiver.close();
+    }
+
+    Collection<Span> spans = psr.getSpans();
+    TraceTree traceTree = new TraceTree(spans);
+    Collection<Span> roots = traceTree.getRoots();
+    Assert.assertEquals(numTraces, roots.size());
+
+    Map<String, Span> descriptionToRootSpan = new HashMap<String, Span>();
+    for (Span root : roots) {
+      descriptionToRootSpan.put(root.getDescription(), root);
+    }
+
+    Assert.assertTrue(descriptionToRootSpan.keySet().contains(
+        TraceCreator.RPC_TRACE_ROOT));
+    Assert.assertTrue(descriptionToRootSpan.keySet().contains(
+        TraceCreator.SIMPLE_TRACE_ROOT));
+    Assert.assertTrue(descriptionToRootSpan.keySet().contains(
+        TraceCreator.THREADED_TRACE_ROOT));
+
+    Multimap<Long, Span> spansByParentId = traceTree.getSpansByParentIdMap();
+    Span rpcTraceRoot = descriptionToRootSpan.get(TraceCreator.RPC_TRACE_ROOT);
+    Assert.assertEquals(1, spansByParentId.get(rpcTraceRoot.getSpanId()).size());
+
+    Span rpcTraceChild1 = spansByParentId.get(rpcTraceRoot.getSpanId())
+        .iterator().next();
+    Assert.assertEquals(1, spansByParentId.get(rpcTraceChild1.getSpanId()).size());
+
+    Span rpcTraceChild2 = spansByParentId.get(rpcTraceChild1.getSpanId())
+        .iterator().next();
+    Assert.assertEquals(1, spansByParentId.get(rpcTraceChild2.getSpanId()).size());
+
+    Span rpcTraceChild3 = spansByParentId.get(rpcTraceChild2.getSpanId())
+        .iterator().next();
+    Assert.assertEquals(0, spansByParentId.get(rpcTraceChild3.getSpanId()).size());
+  }
+
+  private void runTraceCreatorTraces(TraceCreator tc) {
+    tc.createThreadedTrace();
+    tc.createSimpleTrace();
+    tc.createSampleRpcTrace();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/apache/htrace/TestHTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/TestHTraceConfiguration.java b/htrace-core/src/test/java/org/apache/htrace/TestHTraceConfiguration.java
new file mode 100644
index 0000000..440a826
--- /dev/null
+++ b/htrace-core/src/test/java/org/apache/htrace/TestHTraceConfiguration.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.htrace.HTraceConfiguration;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class TestHTraceConfiguration {
+  @Test
+  public void testGetBoolean() throws Exception {
+
+    Map<String, String> m = new HashMap<String, String>();
+    m.put("testTrue", " True");
+    m.put("testFalse", "falsE ");
+    HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
+
+    // Tests for value being there
+    assertTrue(configuration.getBoolean("testTrue", false));
+    assertFalse(configuration.getBoolean("testFalse", true));
+
+    // Test for absent
+    assertTrue(configuration.getBoolean("absent", true));
+    assertFalse(configuration.getBoolean("absent", false));
+  }
+
+  @Test
+  public void testGetInt() throws Exception {
+    Map<String, String> m = new HashMap<String, String>();
+    m.put("a", "100");
+    m.put("b", "0");
+    m.put("c", "-100");
+    m.put("d", "5");
+
+    HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
+    assertEquals(100, configuration.getInt("a", -999));
+    assertEquals(0, configuration.getInt("b", -999));
+    assertEquals(-100, configuration.getInt("c", -999));
+    assertEquals(5, configuration.getInt("d", -999));
+    assertEquals(-999, configuration.getInt("absent", -999));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/apache/htrace/TestSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/TestSampler.java b/htrace-core/src/test/java/org/apache/htrace/TestSampler.java
new file mode 100644
index 0000000..81b965e
--- /dev/null
+++ b/htrace-core/src/test/java/org/apache/htrace/TestSampler.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import org.apache.htrace.Sampler;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceInfo;
+import org.apache.htrace.TraceScope;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestSampler {
+  @Test
+  public void testParamterizedSampler() {
+    TestParamSampler sampler = new TestParamSampler();
+    TraceScope s = Trace.startSpan("test", sampler, 1);
+    Assert.assertNotNull(s.getSpan());
+    s.close();
+    s = Trace.startSpan("test", sampler, -1);
+    Assert.assertNull(s.getSpan());
+    s.close();
+  }
+
+  @Test
+  public void testAlwaysSampler() {
+    TraceScope cur = Trace.startSpan("test", new TraceInfo(0, 0));
+    Assert.assertNotNull(cur);
+    cur.close();
+  }
+
+  private class TestParamSampler implements Sampler<Integer> {
+
+    @Override
+    public boolean next(Integer info) {
+      return info > 0;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/apache/htrace/TraceCreator.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/TraceCreator.java b/htrace-core/src/test/java/org/apache/htrace/TraceCreator.java
new file mode 100644
index 0000000..f577656
--- /dev/null
+++ b/htrace-core/src/test/java/org/apache/htrace/TraceCreator.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace;
+
+import java.util.Collection;
+import java.util.Random;
+
+import org.apache.htrace.Sampler;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceInfo;
+import org.apache.htrace.TraceScope;
+
+/**
+ * Does some stuff and traces it.
+ */
+public class TraceCreator {
+
+  public static final String RPC_TRACE_ROOT = "createSampleRpcTrace";
+  public static final String THREADED_TRACE_ROOT = "createThreadedTrace";
+  public static final String SIMPLE_TRACE_ROOT = "createSimpleTrace";
+
+  /**
+   * Takes as input the SpanReceiver that should used as the sink for Spans when
+   * createDemoTrace() is called.
+   *
+   * @param receiver
+   */
+  public TraceCreator(SpanReceiver receiver) {
+    Trace.addReceiver(receiver);
+  }
+
+  /**
+   * Takes as input the SpanReceivers that should used as the sink for Spans
+   * when createDemoTrace() is called.
+   *
+   * @param receivers
+   */
+  public TraceCreator(Collection<SpanReceiver> receivers) {
+    for (SpanReceiver receiver : receivers) {
+      Trace.addReceiver(receiver);
+    }
+  }
+
+  public void createSampleRpcTrace() {
+    TraceScope s = Trace.startSpan(RPC_TRACE_ROOT, Sampler.ALWAYS);
+    try {
+      pretendRpcSend();
+    } finally {
+      s.close();
+    }
+  }
+
+  public void createSimpleTrace() {
+    TraceScope s = Trace.startSpan(SIMPLE_TRACE_ROOT, Sampler.ALWAYS);
+    try {
+      importantWork1();
+    } finally {
+      s.close();
+    }
+  }
+
+  /**
+   * Creates the demo trace (will create different traces from call to call).
+   */
+  public void createThreadedTrace() {
+    TraceScope s = Trace.startSpan(THREADED_TRACE_ROOT, Sampler.ALWAYS);
+    try {
+      Random r = new Random();
+      int numThreads = r.nextInt(4) + 1;
+      Thread[] threads = new Thread[numThreads];
+
+      for (int i = 0; i < numThreads; i++) {
+        threads[i] = new Thread(Trace.wrap(new MyRunnable()));
+      }
+      for (int i = 0; i < numThreads; i++) {
+        threads[i].start();
+      }
+      for (int i = 0; i < numThreads; i++) {
+        try {
+          threads[i].join();
+        } catch (InterruptedException e) {
+        }
+      }
+      importantWork1();
+    } finally {
+      s.close();
+    }
+  }
+
+  private void importantWork1() {
+    TraceScope cur = Trace.startSpan("important work 1");
+    try {
+      Thread.sleep((long) (2000 * Math.random()));
+      importantWork2();
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+    } finally {
+      cur.close();
+    }
+  }
+
+  private void importantWork2() {
+    TraceScope cur = Trace.startSpan("important work 2");
+    try {
+      Thread.sleep((long) (2000 * Math.random()));
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+    } finally {
+      cur.close();
+    }
+  }
+
+  private class MyRunnable implements Runnable {
+    @Override
+    public void run() {
+      try {
+        Thread.sleep(750);
+        Random r = new Random();
+        int importantNumber = 100 / r.nextInt(3);
+        System.out.println("Important number: " + importantNumber);
+      } catch (InterruptedException ie) {
+        Thread.currentThread().interrupt();
+      } catch (ArithmeticException ae) {
+        TraceScope c = Trace.startSpan("dealing with arithmetic exception.");
+        try {
+          Thread.sleep((long) (3000 * Math.random()));
+        } catch (InterruptedException ie1) {
+          Thread.currentThread().interrupt();
+        } finally {
+          c.close();
+        }
+      }
+    }
+  }
+
+  public void pretendRpcSend() {
+    pretendRpcReceiveWithTraceInfo(TraceInfo.fromSpan(Trace.currentSpan()));
+  }
+
+  public void pretendRpcReceiveWithTraceInfo(TraceInfo traceInfo) {
+    TraceScope s = Trace.startSpan("received RPC", traceInfo);
+    try {
+      importantWork1();
+    } finally {
+      s.close();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/htrace/TestCountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/htrace/TestCountSampler.java b/htrace-core/src/test/java/org/htrace/TestCountSampler.java
deleted file mode 100644
index 25a0d9e..0000000
--- a/htrace-core/src/test/java/org/htrace/TestCountSampler.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import org.htrace.impl.CountSampler;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestCountSampler {
-
-  @Test
-  public void testNext() {
-    CountSampler half = new CountSampler(2);
-    CountSampler hundred = new CountSampler(100);
-    int halfCount = 0;
-    int hundredCount = 0;
-    for (int i = 0; i < 200; i++) {
-      if (half.next(null))
-        halfCount++;
-      if (hundred.next(null))
-        hundredCount++;
-    }
-    Assert.assertEquals(2, hundredCount);
-    Assert.assertEquals(100, halfCount);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/htrace/TestHTrace.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/htrace/TestHTrace.java b/htrace-core/src/test/java/org/htrace/TestHTrace.java
deleted file mode 100644
index f613755..0000000
--- a/htrace-core/src/test/java/org/htrace/TestHTrace.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import com.google.common.collect.Multimap;
-import org.htrace.impl.LocalFileSpanReceiver;
-import org.htrace.impl.POJOSpanReceiver;
-import org.htrace.impl.StandardOutSpanReceiver;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
-public class TestHTrace {
-
-  public static final String SPAN_FILE_FLAG = "spanFile";
-
-  /**
-   * Basic system test of HTrace.
-   *
-   * @throws Exception
-   */
-  @Test
-  public void testHtrace() throws Exception {
-    final int numTraces = 3;
-    String fileName = System.getProperty(SPAN_FILE_FLAG);
-
-    Collection<SpanReceiver> rcvrs = new HashSet<SpanReceiver>();
-
-    // writes spans to a file if one is provided to maven with
-    // -DspanFile="FILENAME", otherwise writes to standard out.
-    if (fileName != null) {
-      File f = new File(fileName);
-      File parent = f.getParentFile();
-      if (parent != null && !parent.exists() && !parent.mkdirs()) {
-        throw new IllegalArgumentException("Couldn't create file: "
-            + fileName);
-      }
-      HashMap<String, String> conf = new HashMap<String, String>();
-      conf.put("local-file-span-receiver.path", fileName);
-      LocalFileSpanReceiver receiver = new LocalFileSpanReceiver();
-      receiver.configure(HTraceConfiguration.fromMap(conf));
-      rcvrs.add(receiver);
-    } else {
-      rcvrs.add(new StandardOutSpanReceiver());
-    }
-
-    POJOSpanReceiver psr = new POJOSpanReceiver();
-    rcvrs.add(psr);
-    runTraceCreatorTraces(new TraceCreator(rcvrs));
-
-    for (SpanReceiver receiver : rcvrs) {
-      receiver.close();
-    }
-
-    Collection<Span> spans = psr.getSpans();
-    TraceTree traceTree = new TraceTree(spans);
-    Collection<Span> roots = traceTree.getRoots();
-    Assert.assertEquals(numTraces, roots.size());
-
-    Map<String, Span> descriptionToRootSpan = new HashMap<String, Span>();
-    for (Span root : roots) {
-      descriptionToRootSpan.put(root.getDescription(), root);
-    }
-
-    Assert.assertTrue(descriptionToRootSpan.keySet().contains(
-        TraceCreator.RPC_TRACE_ROOT));
-    Assert.assertTrue(descriptionToRootSpan.keySet().contains(
-        TraceCreator.SIMPLE_TRACE_ROOT));
-    Assert.assertTrue(descriptionToRootSpan.keySet().contains(
-        TraceCreator.THREADED_TRACE_ROOT));
-
-    Multimap<Long, Span> spansByParentId = traceTree.getSpansByParentIdMap();
-    Span rpcTraceRoot = descriptionToRootSpan.get(TraceCreator.RPC_TRACE_ROOT);
-    Assert.assertEquals(1, spansByParentId.get(rpcTraceRoot.getSpanId()).size());
-
-    Span rpcTraceChild1 = spansByParentId.get(rpcTraceRoot.getSpanId())
-        .iterator().next();
-    Assert.assertEquals(1, spansByParentId.get(rpcTraceChild1.getSpanId()).size());
-
-    Span rpcTraceChild2 = spansByParentId.get(rpcTraceChild1.getSpanId())
-        .iterator().next();
-    Assert.assertEquals(1, spansByParentId.get(rpcTraceChild2.getSpanId()).size());
-
-    Span rpcTraceChild3 = spansByParentId.get(rpcTraceChild2.getSpanId())
-        .iterator().next();
-    Assert.assertEquals(0, spansByParentId.get(rpcTraceChild3.getSpanId()).size());
-  }
-
-  private void runTraceCreatorTraces(TraceCreator tc) {
-    tc.createThreadedTrace();
-    tc.createSimpleTrace();
-    tc.createSampleRpcTrace();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/htrace/TestHTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/htrace/TestHTraceConfiguration.java b/htrace-core/src/test/java/org/htrace/TestHTraceConfiguration.java
deleted file mode 100644
index 5506ddc..0000000
--- a/htrace-core/src/test/java/org/htrace/TestHTraceConfiguration.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class TestHTraceConfiguration {
-  @Test
-  public void testGetBoolean() throws Exception {
-
-    Map<String, String> m = new HashMap<String, String>();
-    m.put("testTrue", " True");
-    m.put("testFalse", "falsE ");
-    HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
-
-    // Tests for value being there
-    assertTrue(configuration.getBoolean("testTrue", false));
-    assertFalse(configuration.getBoolean("testFalse", true));
-
-    // Test for absent
-    assertTrue(configuration.getBoolean("absent", true));
-    assertFalse(configuration.getBoolean("absent", false));
-  }
-
-  @Test
-  public void testGetInt() throws Exception {
-    Map<String, String> m = new HashMap<String, String>();
-    m.put("a", "100");
-    m.put("b", "0");
-    m.put("c", "-100");
-    m.put("d", "5");
-
-    HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
-    assertEquals(100, configuration.getInt("a", -999));
-    assertEquals(0, configuration.getInt("b", -999));
-    assertEquals(-100, configuration.getInt("c", -999));
-    assertEquals(5, configuration.getInt("d", -999));
-    assertEquals(-999, configuration.getInt("absent", -999));
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/htrace/TestSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/htrace/TestSampler.java b/htrace-core/src/test/java/org/htrace/TestSampler.java
deleted file mode 100644
index 9bb2e8b..0000000
--- a/htrace-core/src/test/java/org/htrace/TestSampler.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestSampler {
-  @Test
-  public void testParamterizedSampler() {
-    TestParamSampler sampler = new TestParamSampler();
-    TraceScope s = Trace.startSpan("test", sampler, 1);
-    Assert.assertNotNull(s.getSpan());
-    s.close();
-    s = Trace.startSpan("test", sampler, -1);
-    Assert.assertNull(s.getSpan());
-    s.close();
-  }
-
-  @Test
-  public void testAlwaysSampler() {
-    TraceScope cur = Trace.startSpan("test", new TraceInfo(0, 0));
-    Assert.assertNotNull(cur);
-    cur.close();
-  }
-
-  private class TestParamSampler implements Sampler<Integer> {
-
-    @Override
-    public boolean next(Integer info) {
-      return info > 0;
-    }
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-core/src/test/java/org/htrace/TraceCreator.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/htrace/TraceCreator.java b/htrace-core/src/test/java/org/htrace/TraceCreator.java
deleted file mode 100644
index 7a034b8..0000000
--- a/htrace-core/src/test/java/org/htrace/TraceCreator.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.htrace;
-
-import java.util.Collection;
-import java.util.Random;
-
-/**
- * Does some stuff and traces it.
- */
-public class TraceCreator {
-
-  public static final String RPC_TRACE_ROOT = "createSampleRpcTrace";
-  public static final String THREADED_TRACE_ROOT = "createThreadedTrace";
-  public static final String SIMPLE_TRACE_ROOT = "createSimpleTrace";
-
-  /**
-   * Takes as input the SpanReceiver that should used as the sink for Spans when
-   * createDemoTrace() is called.
-   *
-   * @param receiver
-   */
-  public TraceCreator(SpanReceiver receiver) {
-    Trace.addReceiver(receiver);
-  }
-
-  /**
-   * Takes as input the SpanReceivers that should used as the sink for Spans
-   * when createDemoTrace() is called.
-   *
-   * @param receivers
-   */
-  public TraceCreator(Collection<SpanReceiver> receivers) {
-    for (SpanReceiver receiver : receivers) {
-      Trace.addReceiver(receiver);
-    }
-  }
-
-  public void createSampleRpcTrace() {
-    TraceScope s = Trace.startSpan(RPC_TRACE_ROOT, Sampler.ALWAYS);
-    try {
-      pretendRpcSend();
-    } finally {
-      s.close();
-    }
-  }
-
-  public void createSimpleTrace() {
-    TraceScope s = Trace.startSpan(SIMPLE_TRACE_ROOT, Sampler.ALWAYS);
-    try {
-      importantWork1();
-    } finally {
-      s.close();
-    }
-  }
-
-  /**
-   * Creates the demo trace (will create different traces from call to call).
-   */
-  public void createThreadedTrace() {
-    TraceScope s = Trace.startSpan(THREADED_TRACE_ROOT, Sampler.ALWAYS);
-    try {
-      Random r = new Random();
-      int numThreads = r.nextInt(4) + 1;
-      Thread[] threads = new Thread[numThreads];
-
-      for (int i = 0; i < numThreads; i++) {
-        threads[i] = new Thread(Trace.wrap(new MyRunnable()));
-      }
-      for (int i = 0; i < numThreads; i++) {
-        threads[i].start();
-      }
-      for (int i = 0; i < numThreads; i++) {
-        try {
-          threads[i].join();
-        } catch (InterruptedException e) {
-        }
-      }
-      importantWork1();
-    } finally {
-      s.close();
-    }
-  }
-
-  private void importantWork1() {
-    TraceScope cur = Trace.startSpan("important work 1");
-    try {
-      Thread.sleep((long) (2000 * Math.random()));
-      importantWork2();
-    } catch (InterruptedException e) {
-      Thread.currentThread().interrupt();
-    } finally {
-      cur.close();
-    }
-  }
-
-  private void importantWork2() {
-    TraceScope cur = Trace.startSpan("important work 2");
-    try {
-      Thread.sleep((long) (2000 * Math.random()));
-    } catch (InterruptedException e) {
-      Thread.currentThread().interrupt();
-    } finally {
-      cur.close();
-    }
-  }
-
-  private class MyRunnable implements Runnable {
-    @Override
-    public void run() {
-      try {
-        Thread.sleep(750);
-        Random r = new Random();
-        int importantNumber = 100 / r.nextInt(3);
-        System.out.println("Important number: " + importantNumber);
-      } catch (InterruptedException ie) {
-        Thread.currentThread().interrupt();
-      } catch (ArithmeticException ae) {
-        TraceScope c = Trace.startSpan("dealing with arithmetic exception.");
-        try {
-          Thread.sleep((long) (3000 * Math.random()));
-        } catch (InterruptedException ie1) {
-          Thread.currentThread().interrupt();
-        } finally {
-          c.close();
-        }
-      }
-    }
-  }
-
-  public void pretendRpcSend() {
-    pretendRpcReceiveWithTraceInfo(TraceInfo.fromSpan(Trace.currentSpan()));
-  }
-
-  public void pretendRpcReceiveWithTraceInfo(TraceInfo traceInfo) {
-    TraceScope s = Trace.startSpan("received RPC", traceInfo);
-    try {
-      importantWork1();
-    } finally {
-      s.close();
-    }
-  }
-}
\ No newline at end of file


[4/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerServer.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerServer.java b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerServer.java
new file mode 100644
index 0000000..da90008
--- /dev/null
+++ b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerServer.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.viewer;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.http.HttpServer2;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.util.Tool;
+import org.apache.hadoop.util.ToolRunner;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+
+public class HBaseSpanViewerServer implements Tool {
+  private static final Log LOG = LogFactory.getLog(HBaseSpanViewerServer.class);
+  public static final String HTRACE_VIEWER_HTTP_ADDRESS_KEY = "htrace.viewer.http.address";
+  public static final String HTRACE_VIEWER_HTTP_ADDRESS_DEFAULT = "0.0.0.0:16900";
+  public static final String HTRACE_CONF_ATTR = "htrace.conf";
+  public static final String HTRACE_APPDIR = "webapps";
+  public static final String NAME = "htrace";
+
+  private Configuration conf;
+  private HttpServer2 httpServer;
+  private InetSocketAddress httpAddress;
+
+  public void setConf(Configuration conf) {
+    this.conf = conf;
+  }
+
+  public Configuration getConf() {
+    return this.conf;
+  }
+
+  void start() throws IOException {
+    httpAddress = NetUtils.createSocketAddr(
+        conf.get(HTRACE_VIEWER_HTTP_ADDRESS_KEY, HTRACE_VIEWER_HTTP_ADDRESS_DEFAULT));
+    conf.set(HTRACE_VIEWER_HTTP_ADDRESS_KEY, NetUtils.getHostPortString(httpAddress));
+    HttpServer2.Builder builder = new HttpServer2.Builder();
+    builder.setName(NAME).setConf(conf);
+    if (httpAddress.getPort() == 0) {
+      builder.setFindPort(true);
+    }
+    URI uri = URI.create("http://" + NetUtils.getHostPortString(httpAddress));
+    builder.addEndpoint(uri);
+    LOG.info("Starting Web-server for " + NAME + " at: " + uri);
+    httpServer = builder.build();
+    httpServer.setAttribute(HTRACE_CONF_ATTR, conf);
+    httpServer.addServlet("gettraces",
+                          HBaseSpanViewerTracesServlet.PREFIX,
+                          HBaseSpanViewerTracesServlet.class);
+    httpServer.addServlet("getspans",
+                          HBaseSpanViewerSpansServlet.PREFIX + "/*",
+                          HBaseSpanViewerSpansServlet.class);
+
+    // for webapps/htrace bundled in jar.
+    String rb = httpServer.getClass()
+                          .getClassLoader()
+                          .getResource("webapps/" + NAME)
+                          .toString();
+    httpServer.getWebAppContext().setResourceBase(rb);
+
+    httpServer.start();
+    httpAddress = httpServer.getConnectorAddress(0);
+  }
+
+  void join() throws Exception {
+    if (httpServer != null) {
+      httpServer.join();
+    }
+  }
+
+  void stop() throws Exception {
+    if (httpServer != null) {
+      httpServer.stop();
+    }
+  }
+
+  InetSocketAddress getHttpAddress() {
+    return httpAddress;
+  }
+
+  public int run(String[] args) throws Exception {
+    start();
+    join();
+    stop();
+    return 0;
+  }
+
+  /**
+   * @throws IOException
+   */
+  public static void main(String[] args) throws Exception {
+    ToolRunner.run(HBaseConfiguration.create(), new HBaseSpanViewerServer(), args);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerSpansServlet.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerSpansServlet.java b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerSpansServlet.java
new file mode 100644
index 0000000..8f3f50f
--- /dev/null
+++ b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerSpansServlet.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.viewer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.util.ServletUtil;
+import org.apache.htrace.protobuf.generated.SpanProtos;
+
+public class HBaseSpanViewerSpansServlet extends HttpServlet {
+  private static final Log LOG = LogFactory.getLog(HBaseSpanViewerSpansServlet.class);
+  public static final String PREFIX = "/getspans";
+  private static final ThreadLocal<HBaseSpanViewer> tlviewer =
+      new ThreadLocal<HBaseSpanViewer>() {
+        @Override
+        protected HBaseSpanViewer initialValue() {
+          return null;
+        }
+      };
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public void doGet(HttpServletRequest request, HttpServletResponse response)
+      throws ServletException, IOException {
+    final String path =
+        validatePath(ServletUtil.getDecodedPath(request, PREFIX));
+    if (path == null) {
+      response.setContentType("text/plain");
+      response.getWriter().print("Invalid input");
+      return;
+    }
+    HBaseSpanViewer viewer = tlviewer.get();
+    if (viewer == null) {
+      final Configuration conf = (Configuration) getServletContext()
+        .getAttribute(HBaseSpanViewerServer.HTRACE_CONF_ATTR);
+      viewer = new HBaseSpanViewer(conf);
+      tlviewer.set(viewer);
+    }
+    Long traceid = Long.parseLong(path.substring(1));
+    response.setContentType("application/javascript");
+    PrintWriter out = response.getWriter();
+    out.print("[");
+    boolean first = true;
+    for (SpanProtos.Span span : viewer.getSpans(traceid)) {
+      if (first) {
+        first = false;
+      } else {
+        out.print(",");
+      }
+      out.print(HBaseSpanViewer.toJsonString(span));
+    }
+    out.print("]");
+  }
+
+  @Override
+  public void init() throws ServletException {
+  }
+
+  @Override
+  public void destroy() {
+    HBaseSpanViewer viewer = tlviewer.get();
+    if (viewer != null) {
+      viewer.close();
+    }
+  }
+
+  public static String validatePath(String p) {
+    return p == null || p.length() == 0?
+      null: new Path(p).toUri().getPath();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerTracesServlet.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerTracesServlet.java b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerTracesServlet.java
new file mode 100644
index 0000000..b0370c4
--- /dev/null
+++ b/htrace-hbase/src/main/java/org/apache/htrace/viewer/HBaseSpanViewerTracesServlet.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.viewer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.util.ServletUtil;
+import org.apache.htrace.protobuf.generated.SpanProtos;
+
+public class HBaseSpanViewerTracesServlet extends HttpServlet {
+  private static final Log LOG = LogFactory.getLog(HBaseSpanViewerTracesServlet.class);
+  public static final String PREFIX = "/gettraces";
+  private static final ThreadLocal<HBaseSpanViewer> tlviewer =
+      new ThreadLocal<HBaseSpanViewer>() {
+        @Override
+        protected HBaseSpanViewer initialValue() {
+          return null;
+        }
+      };
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public void doGet(HttpServletRequest request, HttpServletResponse response)
+      throws ServletException, IOException {
+    HBaseSpanViewer viewer = tlviewer.get();
+    if (viewer == null) {
+      final Configuration conf = (Configuration) getServletContext()
+        .getAttribute(HBaseSpanViewerServer.HTRACE_CONF_ATTR);
+      viewer = new HBaseSpanViewer(conf);
+      tlviewer.set(viewer);
+    }
+    response.setContentType("application/javascript");
+    PrintWriter out = response.getWriter();
+    out.print("[");
+    boolean first = true;
+    for (SpanProtos.Span span : viewer.getRootSpans()) {
+      if (first) {
+        first = false;
+      } else {
+        out.print(",");
+      }
+      out.print(HBaseSpanViewer.toJsonString(span));
+    }
+    out.print("]");
+  }
+
+  @Override
+  public void init() throws ServletException {
+  }
+
+  @Override
+  public void destroy() {
+    HBaseSpanViewer viewer = tlviewer.get();
+    if (viewer != null) {
+      viewer.close();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/htrace/impl/HBaseSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/htrace/impl/HBaseSpanReceiver.java b/htrace-hbase/src/main/java/org/htrace/impl/HBaseSpanReceiver.java
deleted file mode 100644
index 85af08c..0000000
--- a/htrace-hbase/src/main/java/org/htrace/impl/HBaseSpanReceiver.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.htrace.impl;
-
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.client.HConnection;
-import org.apache.hadoop.hbase.client.HConnectionManager;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.trace.HBaseHTraceConfiguration;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.htrace.HTraceConfiguration;
-import org.htrace.Sampler;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-import org.htrace.TimelineAnnotation;
-import org.htrace.Trace;
-import org.htrace.TraceScope;
-import org.htrace.protobuf.generated.SpanProtos;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * HBase is an open source distributed datastore.
- * This span receiver store spans into HBase.
- * HTrace spans are queued into a blocking queue.
- * From there background worker threads will send them
- * to a HBase database.
- */
-public class HBaseSpanReceiver implements SpanReceiver {
-  private static final Log LOG = LogFactory.getLog(HBaseSpanReceiver.class);
-
-  public static final String COLLECTOR_QUORUM_KEY = "htrace.hbase.collector-quorum";
-  public static final String DEFAULT_COLLECTOR_QUORUM = "127.0.0.1";
-  public static final String ZOOKEEPER_CLIENT_PORT_KEY = "htrace.hbase.zookeeper.property.clientPort";
-  public static final int DEFAULT_ZOOKEEPER_CLIENT_PORT = 2181;
-  public static final String ZOOKEEPER_ZNODE_PARENT_KEY = "htrace.hbase.zookeeper.znode.parent";
-  public static final String DEFAULT_ZOOKEEPER_ZNODE_PARENT = "/hbase";
-  public static final String NUM_THREADS_KEY = "htrace.hbase.num-threads";
-  public static final int DEFAULT_NUM_THREADS = 1;
-  public static final String MAX_SPAN_BATCH_SIZE_KEY = "htrace.hbase.batch.size";
-  public static final int DEFAULT_MAX_SPAN_BATCH_SIZE = 100;
-  public static final String TABLE_KEY = "htrace.hbase.table";
-  public static final String DEFAULT_TABLE = "htrace";
-  public static final String COLUMNFAMILY_KEY = "htrace.hbase.columnfamily";
-  public static final String DEFAULT_COLUMNFAMILY = "s";
-  public static final String INDEXFAMILY_KEY = "htrace.hbase.indexfamily";
-  public static final String DEFAULT_INDEXFAMILY = "i";
-  public static final byte[] INDEX_SPAN_QUAL = Bytes.toBytes("s");
-  public static final byte[] INDEX_TIME_QUAL = Bytes.toBytes("t");
-
-  /**
-   * How long this receiver will try and wait for all threads to shutdown.
-   */
-  private static final int SHUTDOWN_TIMEOUT = 30;
-
-  /**
-   * How many errors in a row before we start dropping traces on the floor.
-   */
-  private static final int MAX_ERRORS = 10;
-
-  /**
-   * The queue that will get all HTrace spans that are to be sent.
-   */
-  private final BlockingQueue<Span> queue;
-
-  /**
-   * Boolean used to signal that the threads should end.
-   */
-  private final AtomicBoolean running = new AtomicBoolean(true);
-
-  /**
-   * The thread factory used to create new ExecutorService.
-   * <p/>
-   * This will be the same factory for the lifetime of this object so that
-   * no thread names will ever be duplicated.
-   */
-  private final ThreadFactory tf;
-
-  ////////////////////
-  /// Variables that will change on each call to configure()
-  ///////////////////
-  private ExecutorService service;
-  private HTraceConfiguration conf;
-  private Configuration hconf;
-  private byte[] table;
-  private byte[] cf;
-  private byte[] icf;
-  private int maxSpanBatchSize;
-
-  public HBaseSpanReceiver() {
-    this.queue = new ArrayBlockingQueue<Span>(1000);
-    this.tf = new ThreadFactoryBuilder().setDaemon(true)
-                                        .setNameFormat("hbaseSpanReceiver-%d")
-                                        .build();
-  }
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-    this.conf = conf;
-    this.hconf = HBaseConfiguration.create();
-    this.table = Bytes.toBytes(conf.get(TABLE_KEY, DEFAULT_TABLE));
-    this.cf = Bytes.toBytes(conf.get(COLUMNFAMILY_KEY, DEFAULT_COLUMNFAMILY));
-    this.icf = Bytes.toBytes(conf.get(INDEXFAMILY_KEY, DEFAULT_INDEXFAMILY));
-    this.maxSpanBatchSize = conf.getInt(MAX_SPAN_BATCH_SIZE_KEY,
-                                        DEFAULT_MAX_SPAN_BATCH_SIZE);
-    String quorum = conf.get(COLLECTOR_QUORUM_KEY, DEFAULT_COLLECTOR_QUORUM);
-    hconf.set(HConstants.ZOOKEEPER_QUORUM, quorum);
-    String znodeParent = conf.get(ZOOKEEPER_ZNODE_PARENT_KEY, DEFAULT_ZOOKEEPER_ZNODE_PARENT);
-    hconf.set(HConstants.ZOOKEEPER_ZNODE_PARENT, znodeParent);
-    int clientPort = conf.getInt(ZOOKEEPER_CLIENT_PORT_KEY, DEFAULT_ZOOKEEPER_CLIENT_PORT);
-    hconf.setInt(HConstants.ZOOKEEPER_CLIENT_PORT, clientPort);
-
-    // If there are already threads runnnig tear them down.
-    if (this.service != null) {
-      this.service.shutdownNow();
-      this.service = null;
-    }
-    int numThreads = conf.getInt(NUM_THREADS_KEY, DEFAULT_NUM_THREADS);
-    this.service = Executors.newFixedThreadPool(numThreads, tf);
-    for (int i = 0; i < numThreads; i++) {
-      this.service.submit(new WriteSpanRunnable());
-    }
-  }
-
-  private class WriteSpanRunnable implements Runnable {
-    private HConnection hconnection;
-    private HTableInterface htable;
-
-    public WriteSpanRunnable() {
-    }
-
-    /**
-     * This runnable sends a HTrace span to the HBase.
-     */
-    @Override
-    public void run() {
-      SpanProtos.Span.Builder sbuilder = SpanProtos.Span.newBuilder();
-      SpanProtos.TimelineAnnotation.Builder tlbuilder =
-          SpanProtos.TimelineAnnotation.newBuilder();
-      List<Span> dequeuedSpans = new ArrayList<Span>(maxSpanBatchSize);
-      long errorCount = 0;
-
-      while (running.get() || queue.size() > 0) {
-        Span firstSpan = null;
-        try {
-          // Block for up to a second. to try and get a span.
-          // We only block for a little bit in order to notice
-          // if the running value has changed
-          firstSpan = queue.poll(1, TimeUnit.SECONDS);
-
-          // If the poll was successful then it's possible that there
-          // will be other spans to get. Try and get them.
-          if (firstSpan != null) {
-            // Add the first one that we got
-            dequeuedSpans.add(firstSpan);
-            // Try and get up to 100 queues
-            queue.drainTo(dequeuedSpans, maxSpanBatchSize - 1);
-          }
-        } catch (InterruptedException ie) {
-          // Ignored.
-        }
-        startClient();
-        if (dequeuedSpans.isEmpty()) {
-          try {
-            this.htable.flushCommits();
-          } catch (IOException e) {
-            LOG.error("failed to flush writes to HBase.");
-            closeClient();
-          }
-          continue;
-        }
-
-        try {
-          for (Span span : dequeuedSpans) {
-            sbuilder.clear()
-                    .setTraceId(span.getTraceId())
-                    .setParentId(span.getParentId())
-                    .setStart(span.getStartTimeMillis())
-                    .setStop(span.getStopTimeMillis())
-                    .setSpanId(span.getSpanId())
-                    .setProcessId(span.getProcessId())
-                    .setDescription(span.getDescription());
-            for (TimelineAnnotation ta : span.getTimelineAnnotations()) {
-              sbuilder.addTimeline(tlbuilder.clear()
-                                            .setTime(ta.getTime())
-                                            .setMessage(ta.getMessage())
-                                            .build());
-            }
-            Put put = new Put(Bytes.toBytes(span.getTraceId()));
-            put.add(HBaseSpanReceiver.this.cf,
-                    sbuilder.build().toByteArray(),
-                    null);
-            if (span.getParentId() == Span.ROOT_SPAN_ID) {
-              put.add(HBaseSpanReceiver.this.icf,
-                      INDEX_TIME_QUAL,
-                      Bytes.toBytes(span.getStartTimeMillis()));
-              put.add(HBaseSpanReceiver.this.icf,
-                      INDEX_SPAN_QUAL,
-                      sbuilder.build().toByteArray());
-            }
-            this.htable.put(put);
-          }
-          // clear the list for the next time through.
-          dequeuedSpans.clear();
-          // reset the error counter.
-          errorCount = 0;
-        } catch (Exception e) {
-          errorCount += 1;
-          // If there have been ten errors in a row start dropping things.
-          if (errorCount < MAX_ERRORS) {
-            try {
-              queue.addAll(dequeuedSpans);
-            } catch (IllegalStateException ex) {
-              LOG.error("Drop " + dequeuedSpans.size() +
-                        " span(s) because writing to HBase failed.");
-            }
-          }
-          closeClient();
-          try {
-            // Since there was an error sleep just a little bit to try and allow the
-            // HBase some time to recover.
-            Thread.sleep(500);
-          } catch (InterruptedException e1) {
-            // Ignored
-          }
-        }
-      }
-      closeClient();
-    }
-
-    /**
-     * Close out the connection.
-     */
-    private void closeClient() {
-      // close out the transport.
-      try {
-        if (this.htable != null) {
-          this.htable.close();
-          this.htable = null;
-        }
-        if (this.hconnection != null) {
-          this.hconnection.close();
-          this.hconnection = null;
-        }
-      } catch (IOException e) {
-        LOG.warn("Failed to close HBase connection. " + e.getMessage());
-      }
-    }
-
-    /**
-     * Re-connect to HBase
-     */
-    private void startClient() {
-      if (this.htable == null) {
-        try {
-          hconnection = HConnectionManager.createConnection(hconf);
-          htable = hconnection.getTable(table);
-        } catch (IOException e) {
-          LOG.warn("Failed to create HBase connection. " + e.getMessage());
-        }
-      }
-    }
-  }
-
-  /**
-   * Close the receiver.
-   * <p/>
-   * This tries to shutdown thread pool.
-   *
-   * @throws IOException
-   */
-  @Override
-  public void close() throws IOException {
-    running.set(false);
-    service.shutdown();
-    try {
-      if (!service.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
-        LOG.error("Was not able to process all remaining spans upon closing in: " +
-            SHUTDOWN_TIMEOUT + " " + TimeUnit.SECONDS +
-            ". Left Spans could be dropped.");
-       }
-    } catch (InterruptedException e1) {
-      LOG.warn("Thread interrupted when terminating executor.", e1);
-    }
-  }
-
-  @Override
-  public void receiveSpan(Span span) {
-    if (running.get()) {
-      try {
-        this.queue.add(span);
-      } catch (IllegalStateException e) {
-        // todo: supress repeating error logs.
-        LOG.error("Error trying to append span (" +
-            span.getDescription() + 
-            ") to the queue. Blocking Queue was full.");
-      }
-    }
-  }
-
-  /**
-   * Run basic test.
-   * @throws IOException
-   */
-  public static void main(String[] args) throws Exception {
-    HBaseSpanReceiver receiver = new HBaseSpanReceiver();
-    receiver.configure(new HBaseHTraceConfiguration(HBaseConfiguration.create()));
-    Trace.addReceiver(receiver);
-    TraceScope parent = 
-        Trace.startSpan("HBaseSpanReceiver.main.parent", Sampler.ALWAYS);
-    Thread.sleep(10);
-    long traceid = parent.getSpan().getTraceId();
-    TraceScope child1 =
-        Trace.startSpan("HBaseSpanReceiver.main.child.1");
-    Thread.sleep(10);
-    TraceScope child2 =
-        Trace.startSpan("HBaseSpanReceiver.main.child.2", parent.getSpan());
-    Thread.sleep(10);
-    TraceScope gchild =
-        Trace.startSpan("HBaseSpanReceiver.main.grandchild");
-    Trace.addTimelineAnnotation("annotation 1.");
-    Thread.sleep(10);
-    Trace.addTimelineAnnotation("annotation 2.");
-    gchild.close();
-    Thread.sleep(10);
-    child2.close();
-    Thread.sleep(10);
-    child1.close();
-    parent.close();
-    receiver.close();
-    System.out.println("trace id: " + traceid);
-  }
-}


[6/8] incubator-htrace git commit: HTRACE-8. Change our base package from org.htrace to org.apache.htrace (cmccabe / stack)

Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/README.md
----------------------------------------------------------------------
diff --git a/htrace-hbase/README.md b/htrace-hbase/README.md
index 970dfdf..b976d70 100644
--- a/htrace-hbase/README.md
+++ b/htrace-hbase/README.md
@@ -30,13 +30,13 @@ Add a configuration that sets HBase as span receiver in hbase-site.xml:
 
     <property>
       <name>hbase.trace.spanreceiver.classes</name>
-      <value>org.htrace.impl.HBaseSpanReceiver</value>
+      <value>org.apache.htrace.impl.HBaseSpanReceiver</value>
     </property>
 
 Starting HBase server in standalone-mode with htrace-hbase jar added
 to the CLASSPATH (use appropriate 'version' -- below we are using 3.0.4).
 
-    $ HBASE_CLASSPATH=$HOME/.m2/repository/org/htrace/htrace-hbase/3.0.4/htrace-hbase-3.0.4.jar $HBASE_HOME/bin/hbase master start
+    $ HBASE_CLASSPATH=$HOME/.m2/repository/org/apache/htrace/htrace-hbase/3.0.4/htrace-hbase-3.0.4.jar $HBASE_HOME/bin/hbase master start
 
 Running HBase shell from another terminal, add the table in which
 tracing spans are stored.  By default it uses the table named
@@ -46,7 +46,7 @@ tracing spans are stored.  By default it uses the table named
 
 Run some tracing from hbase shell (Make sure htrace is on the CLASSPATH when you start the shell):
 
-    $ HBASE_CLASSPATH=$HOME/.m2/repository/org/htrace/htrace-hbase/3.0.4/htrace-hbase-3.0.4.jar ./bin/hbase shell
+    $ HBASE_CLASSPATH=$HOME/.m2/repository/org/apache/htrace/htrace-hbase/3.0.4/htrace-hbase-3.0.4.jar ./bin/hbase shell
 
     hbase(main):002:0> trace 'start'; create 't1', 'f'; trace 'stop'
     ...
@@ -55,11 +55,11 @@ Run some tracing from hbase shell (Make sure htrace is on the CLASSPATH when you
 
 Running the main class of receiver also generate a simple, artificial trace for test:
 
-    $ bin/hbase org.htrace.impl.HBaseSpanReceiver
+    $ bin/hbase org.apache.htrace.impl.HBaseSpanReceiver
 
 Starting viewer process which listens 0.0.0.0:16900 by default.:
 
-    $ HBASE_CLASSPATH=$HOME/.m2/repository/org/htrace/htrace-hbase/3.0.4/htrace-hbase-3.0.4.jar ./bin/hbase org.htrace.viewer.HBaseSpanViewerServer
+    $ HBASE_CLASSPATH=$HOME/.m2/repository/org/apache/htrace/htrace-hbase/3.0.4/htrace-hbase-3.0.4.jar ./bin/hbase org.apache.htrace.viewer.HBaseSpanViewerServer
 
 Accessing http://host:16900/ with Web browser shows you list of traces like below.:
 
@@ -131,7 +131,7 @@ In addition, span viewer server uses
   to specify the name of table and column families.
 
 ```
-$ bin/hbase org.htrace.viewer.HBaseSpanViewerServer \
+$ bin/hbase org.apache.htrace.viewer.HBaseSpanViewerServer \
     -Dhtrace.viewer.http.address=0.0.0.0:16900 \
     -Dhbase.zookeeper.quorum=127.0.0.1 \
     -Dhbase.zookeeper.znode.parent=/hbase \

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/pom.xml
----------------------------------------------------------------------
diff --git a/htrace-hbase/pom.xml b/htrace-hbase/pom.xml
index f9f81c9..a10abd6 100644
--- a/htrace-hbase/pom.xml
+++ b/htrace-hbase/pom.xml
@@ -17,7 +17,7 @@ language governing permissions and limitations under the License. -->
 
   <parent>
     <artifactId>htrace</artifactId>
-    <groupId>org.htrace</groupId>
+    <groupId>org.apache.htrace</groupId>
     <version>3.0.4</version>
   </parent>
 
@@ -89,13 +89,13 @@ language governing permissions and limitations under the License. -->
   <dependencies>
     <!-- Module deps. -->
     <dependency>
-      <groupId>org.htrace</groupId>
+      <groupId>org.apache.htrace</groupId>
       <artifactId>htrace-core</artifactId>
       <version>${project.version}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>org.htrace</groupId>
+      <groupId>org.apache.htrace</groupId>
       <artifactId>htrace-core</artifactId>
       <version>${project.version}</version>
       <classifier>tests</classifier>
@@ -130,7 +130,7 @@ language governing permissions and limitations under the License. -->
       <version>${hbase.version}</version>
       <exclusions>
         <exclusion>
-          <groupId>org.htrace</groupId>
+          <groupId>org.apache.htrace</groupId>
           <artifactId>htrace-core</artifactId>
         </exclusion>
       </exclusions> 

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/a27cd4da/htrace-hbase/src/main/java/org/apache/htrace/impl/HBaseSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-hbase/src/main/java/org/apache/htrace/impl/HBaseSpanReceiver.java b/htrace-hbase/src/main/java/org/apache/htrace/impl/HBaseSpanReceiver.java
new file mode 100644
index 0000000..4d85e10
--- /dev/null
+++ b/htrace-hbase/src/main/java/org/apache/htrace/impl/HBaseSpanReceiver.java
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.htrace.impl;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HConnection;
+import org.apache.hadoop.hbase.client.HConnectionManager;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.trace.HBaseHTraceConfiguration;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Sampler;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.TimelineAnnotation;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
+import org.apache.htrace.protobuf.generated.SpanProtos;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * HBase is an open source distributed datastore.
+ * This span receiver store spans into HBase.
+ * HTrace spans are queued into a blocking queue.
+ * From there background worker threads will send them
+ * to a HBase database.
+ */
+public class HBaseSpanReceiver implements SpanReceiver {
+  private static final Log LOG = LogFactory.getLog(HBaseSpanReceiver.class);
+
+  public static final String COLLECTOR_QUORUM_KEY = "htrace.hbase.collector-quorum";
+  public static final String DEFAULT_COLLECTOR_QUORUM = "127.0.0.1";
+  public static final String ZOOKEEPER_CLIENT_PORT_KEY = "htrace.hbase.zookeeper.property.clientPort";
+  public static final int DEFAULT_ZOOKEEPER_CLIENT_PORT = 2181;
+  public static final String ZOOKEEPER_ZNODE_PARENT_KEY = "htrace.hbase.zookeeper.znode.parent";
+  public static final String DEFAULT_ZOOKEEPER_ZNODE_PARENT = "/hbase";
+  public static final String NUM_THREADS_KEY = "htrace.hbase.num-threads";
+  public static final int DEFAULT_NUM_THREADS = 1;
+  public static final String MAX_SPAN_BATCH_SIZE_KEY = "htrace.hbase.batch.size";
+  public static final int DEFAULT_MAX_SPAN_BATCH_SIZE = 100;
+  public static final String TABLE_KEY = "htrace.hbase.table";
+  public static final String DEFAULT_TABLE = "htrace";
+  public static final String COLUMNFAMILY_KEY = "htrace.hbase.columnfamily";
+  public static final String DEFAULT_COLUMNFAMILY = "s";
+  public static final String INDEXFAMILY_KEY = "htrace.hbase.indexfamily";
+  public static final String DEFAULT_INDEXFAMILY = "i";
+  public static final byte[] INDEX_SPAN_QUAL = Bytes.toBytes("s");
+  public static final byte[] INDEX_TIME_QUAL = Bytes.toBytes("t");
+
+  /**
+   * How long this receiver will try and wait for all threads to shutdown.
+   */
+  private static final int SHUTDOWN_TIMEOUT = 30;
+
+  /**
+   * How many errors in a row before we start dropping traces on the floor.
+   */
+  private static final int MAX_ERRORS = 10;
+
+  /**
+   * The queue that will get all HTrace spans that are to be sent.
+   */
+  private final BlockingQueue<Span> queue;
+
+  /**
+   * Boolean used to signal that the threads should end.
+   */
+  private final AtomicBoolean running = new AtomicBoolean(true);
+
+  /**
+   * The thread factory used to create new ExecutorService.
+   * <p/>
+   * This will be the same factory for the lifetime of this object so that
+   * no thread names will ever be duplicated.
+   */
+  private final ThreadFactory tf;
+
+  ////////////////////
+  /// Variables that will change on each call to configure()
+  ///////////////////
+  private ExecutorService service;
+  private HTraceConfiguration conf;
+  private Configuration hconf;
+  private byte[] table;
+  private byte[] cf;
+  private byte[] icf;
+  private int maxSpanBatchSize;
+
+  public HBaseSpanReceiver() {
+    this.queue = new ArrayBlockingQueue<Span>(1000);
+    this.tf = new ThreadFactoryBuilder().setDaemon(true)
+                                        .setNameFormat("hbaseSpanReceiver-%d")
+                                        .build();
+  }
+
+  @Override
+  public void configure(HTraceConfiguration conf) {
+    this.conf = conf;
+    this.hconf = HBaseConfiguration.create();
+    this.table = Bytes.toBytes(conf.get(TABLE_KEY, DEFAULT_TABLE));
+    this.cf = Bytes.toBytes(conf.get(COLUMNFAMILY_KEY, DEFAULT_COLUMNFAMILY));
+    this.icf = Bytes.toBytes(conf.get(INDEXFAMILY_KEY, DEFAULT_INDEXFAMILY));
+    this.maxSpanBatchSize = conf.getInt(MAX_SPAN_BATCH_SIZE_KEY,
+                                        DEFAULT_MAX_SPAN_BATCH_SIZE);
+    String quorum = conf.get(COLLECTOR_QUORUM_KEY, DEFAULT_COLLECTOR_QUORUM);
+    hconf.set(HConstants.ZOOKEEPER_QUORUM, quorum);
+    String znodeParent = conf.get(ZOOKEEPER_ZNODE_PARENT_KEY, DEFAULT_ZOOKEEPER_ZNODE_PARENT);
+    hconf.set(HConstants.ZOOKEEPER_ZNODE_PARENT, znodeParent);
+    int clientPort = conf.getInt(ZOOKEEPER_CLIENT_PORT_KEY, DEFAULT_ZOOKEEPER_CLIENT_PORT);
+    hconf.setInt(HConstants.ZOOKEEPER_CLIENT_PORT, clientPort);
+
+    // If there are already threads runnnig tear them down.
+    if (this.service != null) {
+      this.service.shutdownNow();
+      this.service = null;
+    }
+    int numThreads = conf.getInt(NUM_THREADS_KEY, DEFAULT_NUM_THREADS);
+    this.service = Executors.newFixedThreadPool(numThreads, tf);
+    for (int i = 0; i < numThreads; i++) {
+      this.service.submit(new WriteSpanRunnable());
+    }
+  }
+
+  private class WriteSpanRunnable implements Runnable {
+    private HConnection hconnection;
+    private HTableInterface htable;
+
+    public WriteSpanRunnable() {
+    }
+
+    /**
+     * This runnable sends a HTrace span to the HBase.
+     */
+    @Override
+    public void run() {
+      SpanProtos.Span.Builder sbuilder = SpanProtos.Span.newBuilder();
+      SpanProtos.TimelineAnnotation.Builder tlbuilder =
+          SpanProtos.TimelineAnnotation.newBuilder();
+      List<Span> dequeuedSpans = new ArrayList<Span>(maxSpanBatchSize);
+      long errorCount = 0;
+
+      while (running.get() || queue.size() > 0) {
+        Span firstSpan = null;
+        try {
+          // Block for up to a second. to try and get a span.
+          // We only block for a little bit in order to notice
+          // if the running value has changed
+          firstSpan = queue.poll(1, TimeUnit.SECONDS);
+
+          // If the poll was successful then it's possible that there
+          // will be other spans to get. Try and get them.
+          if (firstSpan != null) {
+            // Add the first one that we got
+            dequeuedSpans.add(firstSpan);
+            // Try and get up to 100 queues
+            queue.drainTo(dequeuedSpans, maxSpanBatchSize - 1);
+          }
+        } catch (InterruptedException ie) {
+          // Ignored.
+        }
+        startClient();
+        if (dequeuedSpans.isEmpty()) {
+          try {
+            this.htable.flushCommits();
+          } catch (IOException e) {
+            LOG.error("failed to flush writes to HBase.");
+            closeClient();
+          }
+          continue;
+        }
+
+        try {
+          for (Span span : dequeuedSpans) {
+            sbuilder.clear()
+                    .setTraceId(span.getTraceId())
+                    .setParentId(span.getParentId())
+                    .setStart(span.getStartTimeMillis())
+                    .setStop(span.getStopTimeMillis())
+                    .setSpanId(span.getSpanId())
+                    .setProcessId(span.getProcessId())
+                    .setDescription(span.getDescription());
+            for (TimelineAnnotation ta : span.getTimelineAnnotations()) {
+              sbuilder.addTimeline(tlbuilder.clear()
+                                            .setTime(ta.getTime())
+                                            .setMessage(ta.getMessage())
+                                            .build());
+            }
+            Put put = new Put(Bytes.toBytes(span.getTraceId()));
+            put.add(HBaseSpanReceiver.this.cf,
+                    sbuilder.build().toByteArray(),
+                    null);
+            if (span.getParentId() == Span.ROOT_SPAN_ID) {
+              put.add(HBaseSpanReceiver.this.icf,
+                      INDEX_TIME_QUAL,
+                      Bytes.toBytes(span.getStartTimeMillis()));
+              put.add(HBaseSpanReceiver.this.icf,
+                      INDEX_SPAN_QUAL,
+                      sbuilder.build().toByteArray());
+            }
+            this.htable.put(put);
+          }
+          // clear the list for the next time through.
+          dequeuedSpans.clear();
+          // reset the error counter.
+          errorCount = 0;
+        } catch (Exception e) {
+          errorCount += 1;
+          // If there have been ten errors in a row start dropping things.
+          if (errorCount < MAX_ERRORS) {
+            try {
+              queue.addAll(dequeuedSpans);
+            } catch (IllegalStateException ex) {
+              LOG.error("Drop " + dequeuedSpans.size() +
+                        " span(s) because writing to HBase failed.");
+            }
+          }
+          closeClient();
+          try {
+            // Since there was an error sleep just a little bit to try and allow the
+            // HBase some time to recover.
+            Thread.sleep(500);
+          } catch (InterruptedException e1) {
+            // Ignored
+          }
+        }
+      }
+      closeClient();
+    }
+
+    /**
+     * Close out the connection.
+     */
+    private void closeClient() {
+      // close out the transport.
+      try {
+        if (this.htable != null) {
+          this.htable.close();
+          this.htable = null;
+        }
+        if (this.hconnection != null) {
+          this.hconnection.close();
+          this.hconnection = null;
+        }
+      } catch (IOException e) {
+        LOG.warn("Failed to close HBase connection. " + e.getMessage());
+      }
+    }
+
+    /**
+     * Re-connect to HBase
+     */
+    private void startClient() {
+      if (this.htable == null) {
+        try {
+          hconnection = HConnectionManager.createConnection(hconf);
+          htable = hconnection.getTable(table);
+        } catch (IOException e) {
+          LOG.warn("Failed to create HBase connection. " + e.getMessage());
+        }
+      }
+    }
+  }
+
+  /**
+   * Close the receiver.
+   * <p/>
+   * This tries to shutdown thread pool.
+   *
+   * @throws IOException
+   */
+  @Override
+  public void close() throws IOException {
+    running.set(false);
+    service.shutdown();
+    try {
+      if (!service.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
+        LOG.error("Was not able to process all remaining spans upon closing in: " +
+            SHUTDOWN_TIMEOUT + " " + TimeUnit.SECONDS +
+            ". Left Spans could be dropped.");
+       }
+    } catch (InterruptedException e1) {
+      LOG.warn("Thread interrupted when terminating executor.", e1);
+    }
+  }
+
+  @Override
+  public void receiveSpan(Span span) {
+    if (running.get()) {
+      try {
+        this.queue.add(span);
+      } catch (IllegalStateException e) {
+        // todo: supress repeating error logs.
+        LOG.error("Error trying to append span (" +
+            span.getDescription() +
+            ") to the queue. Blocking Queue was full.");
+      }
+    }
+  }
+
+  /**
+   * Run basic test.
+   * @throws IOException
+   *
+   *
+   * TODO: !!!!! FIX !!!! Circular dependency back to HBase!!!
+   *
+  public static void main(String[] args) throws Exception {
+    HBaseSpanReceiver receiver = new HBaseSpanReceiver();
+    receiver.configure(new HBaseHTraceConfiguration(HBaseConfiguration.create()));
+    Trace.addReceiver(receiver);
+    TraceScope parent =
+        Trace.startSpan("HBaseSpanReceiver.main.parent", Sampler.ALWAYS);
+    Thread.sleep(10);
+    long traceid = parent.getSpan().getTraceId();
+    TraceScope child1 =
+        Trace.startSpan("HBaseSpanReceiver.main.child.1");
+    Thread.sleep(10);
+    TraceScope child2 =
+        Trace.startSpan("HBaseSpanReceiver.main.child.2", parent.getSpan());
+    Thread.sleep(10);
+    TraceScope gchild =
+        Trace.startSpan("HBaseSpanReceiver.main.grandchild");
+    Trace.addTimelineAnnotation("annotation 1.");
+    Thread.sleep(10);
+    Trace.addTimelineAnnotation("annotation 2.");
+    gchild.close();
+    Thread.sleep(10);
+    child2.close();
+    Thread.sleep(10);
+    child1.close();
+    parent.close();
+    receiver.close();
+    System.out.println("trace id: " + traceid);
+  }
+   */
+}