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:44 UTC

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

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);
-
-}