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 2015/08/18 21:05:19 UTC

[4/4] incubator-htrace git commit: HTRACE-211. Move htrace-core classes to the org.apache.htrace.core namespace (cmccabe)

HTRACE-211. Move htrace-core classes to the org.apache.htrace.core namespace (cmccabe)


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

Branch: refs/heads/master
Commit: fd889b659604c227045200fce4fd8eadf85e7166
Parents: afa0b71
Author: Colin P. Mccabe <cm...@apache.org>
Authored: Tue Aug 18 11:03:37 2015 -0700
Committer: Colin P. Mccabe <cm...@apache.org>
Committed: Tue Aug 18 11:13:10 2015 -0700

----------------------------------------------------------------------
 .../org/apache/htrace/HTraceConfiguration.java  | 109 ------
 .../main/java/org/apache/htrace/NullScope.java  |  44 ---
 .../main/java/org/apache/htrace/Sampler.java    |  42 ---
 .../java/org/apache/htrace/SamplerBuilder.java  |  92 -----
 .../src/main/java/org/apache/htrace/Span.java   | 192 ----------
 .../src/main/java/org/apache/htrace/SpanId.java | 149 --------
 .../java/org/apache/htrace/SpanReceiver.java    |  39 --
 .../org/apache/htrace/SpanReceiverBuilder.java  | 138 --------
 .../org/apache/htrace/TimelineAnnotation.java   |  40 ---
 .../src/main/java/org/apache/htrace/Trace.java  | 223 ------------
 .../main/java/org/apache/htrace/TraceScope.java |  99 ------
 .../src/main/java/org/apache/htrace/Tracer.java | 130 -------
 .../org/apache/htrace/core/AlwaysSampler.java   |  33 ++
 .../org/apache/htrace/core/CountSampler.java    |  39 ++
 .../apache/htrace/core/HTraceConfiguration.java | 109 ++++++
 .../htrace/core/LocalFileSpanReceiver.java      | 261 ++++++++++++++
 .../java/org/apache/htrace/core/MilliSpan.java  | 348 ++++++++++++++++++
 .../org/apache/htrace/core/NeverSampler.java    |  34 ++
 .../java/org/apache/htrace/core/NullScope.java  |  44 +++
 .../apache/htrace/core/POJOSpanReceiver.java    |  49 +++
 .../apache/htrace/core/ProbabilitySampler.java  |  46 +++
 .../java/org/apache/htrace/core/Sampler.java    |  39 ++
 .../org/apache/htrace/core/SamplerBuilder.java  |  91 +++++
 .../main/java/org/apache/htrace/core/Span.java  | 192 ++++++++++
 .../java/org/apache/htrace/core/SpanId.java     | 149 ++++++++
 .../org/apache/htrace/core/SpanReceiver.java    |  39 ++
 .../apache/htrace/core/SpanReceiverBuilder.java | 138 ++++++++
 .../htrace/core/StandardOutSpanReceiver.java    |  42 +++
 .../apache/htrace/core/TimelineAnnotation.java  |  40 +++
 .../main/java/org/apache/htrace/core/Trace.java | 219 ++++++++++++
 .../org/apache/htrace/core/TraceCallable.java   |  65 ++++
 .../htrace/core/TraceExecutorService.java       | 118 +++++++
 .../java/org/apache/htrace/core/TraceProxy.java |  58 +++
 .../org/apache/htrace/core/TraceRunnable.java   |  64 ++++
 .../java/org/apache/htrace/core/TraceScope.java |  99 ++++++
 .../java/org/apache/htrace/core/Tracer.java     | 129 +++++++
 .../java/org/apache/htrace/core/TracerId.java   | 290 +++++++++++++++
 .../org/apache/htrace/impl/AlwaysSampler.java   |  36 --
 .../org/apache/htrace/impl/CountSampler.java    |  43 ---
 .../htrace/impl/LocalFileSpanReceiver.java      | 264 --------------
 .../java/org/apache/htrace/impl/MilliSpan.java  | 352 -------------------
 .../org/apache/htrace/impl/NeverSampler.java    |  37 --
 .../apache/htrace/impl/POJOSpanReceiver.java    |  53 ---
 .../apache/htrace/impl/ProbabilitySampler.java  |  48 ---
 .../htrace/impl/StandardOutSpanReceiver.java    |  45 ---
 .../java/org/apache/htrace/impl/TracerId.java   | 291 ---------------
 .../apache/htrace/wrappers/TraceCallable.java   |  69 ----
 .../htrace/wrappers/TraceExecutorService.java   | 118 -------
 .../org/apache/htrace/wrappers/TraceProxy.java  |  62 ----
 .../apache/htrace/wrappers/TraceRunnable.java   |  68 ----
 .../java/org/apache/htrace/TestBadClient.java   | 154 --------
 .../org/apache/htrace/TestCountSampler.java     |  43 ---
 .../test/java/org/apache/htrace/TestHTrace.java | 118 -------
 .../apache/htrace/TestHTraceConfiguration.java  |  63 ----
 .../java/org/apache/htrace/TestNullScope.java   |  37 --
 .../java/org/apache/htrace/TestSampler.java     |  59 ----
 .../test/java/org/apache/htrace/TestSpanId.java |  72 ----
 .../apache/htrace/TestSpanReceiverBuilder.java  | 140 --------
 .../java/org/apache/htrace/TraceCreator.java    | 169 ---------
 .../test/java/org/apache/htrace/TraceGraph.java | 179 ----------
 .../org/apache/htrace/core/TestBadClient.java   | 146 ++++++++
 .../apache/htrace/core/TestCountSampler.java    |  41 +++
 .../java/org/apache/htrace/core/TestHTrace.java | 116 ++++++
 .../htrace/core/TestHTraceConfiguration.java    |  62 ++++
 .../htrace/core/TestLocalFileSpanReceiver.java  |  70 ++++
 .../org/apache/htrace/core/TestMilliSpan.java   | 145 ++++++++
 .../org/apache/htrace/core/TestNullScope.java   |  34 ++
 .../org/apache/htrace/core/TestSampler.java     |  55 +++
 .../java/org/apache/htrace/core/TestSpanId.java |  72 ++++
 .../htrace/core/TestSpanReceiverBuilder.java    | 139 ++++++++
 .../org/apache/htrace/core/TestTracerId.java    |  47 +++
 .../org/apache/htrace/core/TraceCreator.java    | 169 +++++++++
 .../java/org/apache/htrace/core/TraceGraph.java | 176 ++++++++++
 .../htrace/impl/TestLocalFileSpanReceiver.java  |  75 ----
 .../org/apache/htrace/impl/TestMilliSpan.java   | 148 --------
 .../org/apache/htrace/impl/TestTracerId.java    |  47 ---
 76 files changed, 4007 insertions(+), 4087 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/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
deleted file mode 100644
index 4580dff..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/HTraceConfiguration.java
+++ /dev/null
@@ -1,109 +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.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);
-
-  private static final Map<String, String> EMPTY_MAP = new HashMap<String, String>(1);
-
-  /**
-   * An empty HTrace configuration.
-   */
-  public static final HTraceConfiguration EMPTY = fromMap(EMPTY_MAP);
-
-  /**
-   * Create an HTrace configuration from a map.
-   *
-   * @param conf    The map to create the configuration from.
-   * @return        The new configuration.
-   */
-  public static HTraceConfiguration fromMap(Map<String, String> conf) {
-    return new MapConf(conf);
-  }
-
-  public static HTraceConfiguration fromKeyValuePairs(String... pairs) {
-    if ((pairs.length % 2) != 0) {
-      throw new RuntimeException("You must specify an equal number of keys " +
-          "and values.");
-    }
-    Map<String, String> conf = new HashMap<String, String>();
-    for (int i = 0; i < pairs.length; i+=2) {
-      conf.put(pairs[i], pairs[i + 1]);
-    }
-    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/fd889b65/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
deleted file mode 100644
index ff9a42c..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/NullScope.java
+++ /dev/null
@@ -1,44 +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.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 Span detach() {
-    return null;
-  }
-
-  @Override
-  public void close() {
-    return;
-  }
-
-  @Override
-  public String toString() {
-    return "NullScope";
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/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
deleted file mode 100644
index 3bf62aa..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/Sampler.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.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/>
- * For example, the next() function may look like this:
- * <p/>
- * <pre>
- * <code>
- * public boolean next() {
- *   return Math.random() &gt; 0.5;
- * }
- * </code>
- * </pre>
- * This would trace 50% of all gets, 75% of all puts and would not trace any other requests.
- */
-public interface Sampler {
-  public static final Sampler ALWAYS = AlwaysSampler.INSTANCE;
-  public static final Sampler NEVER = NeverSampler.INSTANCE;
-
-  public boolean next();
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/SamplerBuilder.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/SamplerBuilder.java b/htrace-core/src/main/java/org/apache/htrace/SamplerBuilder.java
deleted file mode 100644
index 4364671..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/SamplerBuilder.java
+++ /dev/null
@@ -1,92 +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.apache.htrace;
-
-import java.lang.reflect.Constructor;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.htrace.impl.AlwaysSampler;
-import org.apache.htrace.impl.NeverSampler;
-
-/**
- * A {@link Sampler} builder. It reads a {@link Sampler} class name from the provided
- * configuration using the {@link #SAMPLER_CONF_KEY} key. Unqualified class names
- * are interpreted as members of the {@code org.apache.htrace.impl} package. The {@link #build()}
- * method constructs an instance of that class, initialized with the same configuration.
- */
-public class SamplerBuilder {
-
-  // TODO: should follow the same API as SpanReceiverBuilder
-
-  public final static String SAMPLER_CONF_KEY = "sampler";
-  private final static String DEFAULT_PACKAGE = "org.apache.htrace.impl";
-  private final static ClassLoader classLoader =
-      SamplerBuilder.class.getClassLoader();
-  private final HTraceConfiguration conf;
-  private static final Log LOG = LogFactory.getLog(SamplerBuilder.class);
-
-  public SamplerBuilder(HTraceConfiguration conf) {
-    this.conf = conf;
-  }
-
-  public Sampler build() {
-    Sampler sampler = newSampler();
-    if (LOG.isTraceEnabled()) {
-      LOG.trace("Created new sampler of type " +
-          sampler.getClass().getName(), new Exception());
-    }
-    return sampler;
-  }
-
-  private Sampler newSampler() {
-    String str = conf.get(SAMPLER_CONF_KEY);
-    if (str == null || str.isEmpty()) {
-      return NeverSampler.INSTANCE;
-    }
-    if (!str.contains(".")) {
-      str = DEFAULT_PACKAGE + "." + str;
-    }
-    Class cls = null;
-    try {
-      cls = classLoader.loadClass(str);
-    } catch (ClassNotFoundException e) {
-      LOG.error("SamplerBuilder cannot find sampler class " + str +
-          ": falling back on NeverSampler.");
-      return NeverSampler.INSTANCE;
-    }
-    Constructor<Sampler> ctor = null;
-    try {
-      ctor = cls.getConstructor(HTraceConfiguration.class);
-    } catch (NoSuchMethodException e) {
-      LOG.error("SamplerBuilder cannot find a constructor for class " + str +
-          "which takes an HTraceConfiguration.  Falling back on " +
-          "NeverSampler.");
-      return NeverSampler.INSTANCE;
-    }
-    try {
-      return ctor.newInstance(conf);
-    } catch (ReflectiveOperationException e) {
-      LOG.error("SamplerBuilder reflection error when constructing " + str +
-          ".  Falling back on NeverSampler.", e);
-      return NeverSampler.INSTANCE;
-    } catch (Throwable e) {
-      LOG.error("SamplerBuilder constructor error when constructing " + str +
-          ".  Falling back on NeverSampler.", e);
-      return NeverSampler.INSTANCE;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/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
deleted file mode 100644
index 0897ee9..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/Span.java
+++ /dev/null
@@ -1,192 +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.apache.htrace;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-
-/**
- * Base interface for gathering and reporting statistics about a block of
- * execution.
- * <p/>
- * Spans should form a directed acyclic graph structure.  It should be possible
- * to keep following the parents of a span until you arrive at a span with no
- * parents.<p/>
- */
-@JsonSerialize(using = Span.SpanSerializer.class)
-public interface Span {
-  /**
-   * 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.<p/>
-   *
-   * Will never be null.
-   */
-  String getDescription();
-
-  /**
-   * A pseudo-unique (random) number assigned to this span instance.<p/>
-   *
-   * The spanId is immutable and cannot be changed.  It is safe to access this
-   * from multiple threads.
-   */
-  SpanId getSpanId();
-
-  /**
-   * Create a child span of this span with the given description
-   */
-  Span child(String description);
-
-  @Override
-  String toString();
-
-  /**
-   * Returns the parent IDs of the span.<p/>
-   *
-   * The array will be empty if there are no parents.
-   */
-  SpanId[] getParents();
-
-  /**
-   * Set the parents of this span.<p/>
-   *
-   * Any existing parents will be cleared by this call.
-   */
-  void setParents(SpanId[] parents);
-
-  /**
-   * Add a data annotation associated with this span
-   */
-  void addKVAnnotation(String key, String value);
-
-  /**
-   * Add a timeline annotation associated with this span
-   */
-  void addTimelineAnnotation(String msg);
-
-  /**
-   * Get data associated with this span (read only)<p/>
-   *
-   * Will never be null.
-   */
-  Map<String, String> getKVAnnotations();
-
-  /**
-   * Get any timeline annotations (read only)<p/>
-   *
-   * Will never be null.
-   */
-  List<TimelineAnnotation> getTimelineAnnotations();
-
-  /**
-   * Return a unique id for the process from which this Span originated.<p/>
-   *
-   * Will never be null.
-   */
-  String getTracerId();
-
-  /**
-   * Set the process id of a span.
-   */
-  void setTracerId(String s);
-
-  /**
-   * Serialize to Json
-   */
-  String toJson();
-
-  public static class SpanSerializer extends JsonSerializer<Span> {
-    @Override
-    public void serialize(Span span, JsonGenerator jgen, SerializerProvider provider)
-        throws IOException {
-      jgen.writeStartObject();
-      if (span.getSpanId().isValid()) {
-        jgen.writeStringField("a", span.getSpanId().toString());
-      }
-      if (span.getStartTimeMillis() != 0) {
-        jgen.writeNumberField("b", span.getStartTimeMillis());
-      }
-      if (span.getStopTimeMillis() != 0) {
-        jgen.writeNumberField("e", span.getStopTimeMillis());
-      }
-      if (!span.getDescription().isEmpty()) {
-        jgen.writeStringField("d", span.getDescription());
-      }
-      String tracerId = span.getTracerId();
-      if (!tracerId.isEmpty()) {
-        jgen.writeStringField("r", tracerId);
-      }
-      jgen.writeArrayFieldStart("p");
-      for (SpanId parent : span.getParents()) {
-        jgen.writeString(parent.toString());
-      }
-      jgen.writeEndArray();
-      Map<String, String> traceInfoMap = span.getKVAnnotations();
-      if (!traceInfoMap.isEmpty()) {
-        jgen.writeObjectFieldStart("n");
-        for (Map.Entry<String, String> e : traceInfoMap.entrySet()) {
-          jgen.writeStringField(e.getKey(), e.getValue());
-        }
-        jgen.writeEndObject();
-      }
-      List<TimelineAnnotation> timelineAnnotations =
-          span.getTimelineAnnotations();
-      if (!timelineAnnotations.isEmpty()) {
-        jgen.writeArrayFieldStart("t");
-        for (TimelineAnnotation tl : timelineAnnotations) {
-          jgen.writeStartObject();
-          jgen.writeNumberField("t", tl.getTime());
-          jgen.writeStringField("m", tl.getMessage());
-          jgen.writeEndObject();
-        }
-        jgen.writeEndArray();
-      }
-      jgen.writeEndObject();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/SpanId.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/SpanId.java b/htrace-core/src/main/java/org/apache/htrace/SpanId.java
deleted file mode 100644
index 25dc108..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/SpanId.java
+++ /dev/null
@@ -1,149 +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.apache.htrace;
-
-import java.math.BigInteger;
-import java.lang.Void;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.Random;
-
-/**
- * Uniquely identifies an HTrace span.
- *
- * Span IDs are 128 bits in total.  The upper 64 bits of a span ID is the same
- * as the upper 64 bits of the parent span, if there is one.  The lower 64 bits
- * are always random.
- */
-public final class SpanId implements Comparable<SpanId> {
-  private static final int SPAN_ID_STRING_LENGTH = 32;
-  private final long high;
-  private final long low;
-
-  /**
-   * The invalid span ID, which is all zeroes.
-   *
-   * It is also the "least" span ID in the sense that it is considered
-   * smaller than any other span ID.
-   */
-  public static SpanId INVALID = new SpanId(0, 0);
-
-  private static long nonZeroRand64() {
-    while (true) {
-      long r = ThreadLocalRandom.current().nextLong();
-      if (r != 0) {
-        return r;
-      }
-    }
-  }
-
-  public static SpanId fromRandom() {
-    return new SpanId(nonZeroRand64(), nonZeroRand64());
-  }
-
-  public static SpanId fromString(String str) {
-    if (str.length() != SPAN_ID_STRING_LENGTH) {
-      throw new RuntimeException("Invalid SpanID string: length was not " +
-          SPAN_ID_STRING_LENGTH);
-    }
-    long high =
-      ((Long.parseLong(str.substring(0, 8), 16)) << 32) |
-      (Long.parseLong(str.substring(8, 16), 16));
-    long low =
-      ((Long.parseLong(str.substring(16, 24), 16)) << 32) |
-      (Long.parseLong(str.substring(24, 32), 16));
-    return new SpanId(high, low);
-  }
-
-  public SpanId(long high, long low) {
-    this.high = high;
-    this.low = low;
-  }
-
-  public long getHigh() {
-    return high;
-  }
-
-  public long getLow() {
-    return low;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof SpanId)) {
-      return false;
-    }
-    SpanId other = (SpanId)o;
-    return ((other.high == high) && (other.low == low));
-  }
-
-  @Override
-  public int compareTo(SpanId other) {
-    int cmp = compareAsUnsigned(high, other.high);
-    if (cmp != 0) {
-      return cmp;
-    }
-    return compareAsUnsigned(low, other.low);
-  }
-
-  private static int compareAsUnsigned(long a, long b) {
-    boolean aSign = a < 0;
-    boolean bSign = b < 0;
-    if (aSign != bSign) {
-      if (aSign) {
-        return 1;
-      } else {
-        return -1;
-      }
-    }
-    if (aSign) {
-      a = -a;
-      b = -b;
-    }
-    if (a < b) {
-      return -1;
-    } else if (a > b) {
-      return 1;
-    } else {
-      return 0;
-    }
-  }
-
-  @Override
-  public int hashCode() {
-    return (int)((0xffffffff & (high >> 32))) ^
-           (int)((0xffffffff & (high >> 0))) ^
-           (int)((0xffffffff & (low >> 32))) ^
-           (int)((0xffffffff & (low >> 0)));
-  }
-
-  @Override
-  public String toString() {
-    return String.format("%08x%08x%08x%08x",
-        (0x00000000ffffffffL & (high >> 32)),
-        (0x00000000ffffffffL & high),
-        (0x00000000ffffffffL & (low >> 32)),
-        (0x00000000ffffffffL & low));
-  }
-
-  public boolean isValid() {
-    return (high != 0)  || (low != 0);
-  }
-
-  public SpanId newChildId() {
-    return new SpanId(high, nonZeroRand64());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/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
deleted file mode 100644
index 7ae157b..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/SpanReceiver.java
+++ /dev/null
@@ -1,39 +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.apache.htrace;
-
-
-import java.io.Closeable;
-
-
-/**
- * The collector within a process that is the destination of Spans when a trace is running.
- * {@code SpanReceiver} implementations are expected to provide a constructor with the signature
- * <p>
- * <pre>
- * <code>public SpanReceiverImpl(HTraceConfiguration)</code>
- * </pre>
- * The helper class {@link org.apache.htrace.SpanReceiverBuilder} provides convenient factory
- * methods for creating {@code SpanReceiver} instances from configuration.
- * @see org.apache.htrace.SpanReceiverBuilder
- */
-public interface SpanReceiver extends Closeable {
-  /**
-   * Called when a Span is stopped and can now be stored.
-   */
-  public void receiveSpan(Span span);
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/SpanReceiverBuilder.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/SpanReceiverBuilder.java b/htrace-core/src/main/java/org/apache/htrace/SpanReceiverBuilder.java
deleted file mode 100644
index 15b3af0..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/SpanReceiverBuilder.java
+++ /dev/null
@@ -1,138 +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.apache.htrace;
-
-import java.lang.reflect.Constructor;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * A {@link SpanReceiver} builder. It reads a {@link SpanReceiver} class name from the provided
- * configuration using the {@link #SPAN_RECEIVER_CONF_KEY} key. Unqualified class names
- * are interpreted as members of the {@code org.apache.htrace.impl} package. The {@link #build()}
- * method constructs an instance of that class, initialized with the same configuration.
- */
-public class SpanReceiverBuilder {
-  private static final Log LOG = LogFactory.getLog(SpanReceiverBuilder.class);
-
-  public final static String SPAN_RECEIVER_CONF_KEY = "span.receiver";
-  private final static String DEFAULT_PACKAGE = "org.apache.htrace.impl";
-  private final static ClassLoader classLoader =
-      SpanReceiverBuilder.class.getClassLoader();
-  private final HTraceConfiguration conf;
-  private boolean logErrors;
-  private String spanReceiverClass;
-
-  public SpanReceiverBuilder(HTraceConfiguration conf) {
-    this.conf = conf;
-    reset();
-  }
-
-  /**
-   * Set this builder back to defaults. Any previous calls to {@link #spanReceiverClass(String)}
-   * are overridden by the value provided by configuration.
-   * @return This instance
-   */
-  public SpanReceiverBuilder reset() {
-    this.logErrors = true;
-    this.spanReceiverClass = this.conf.get(SPAN_RECEIVER_CONF_KEY);
-    return this;
-  }
-
-  /**
-   * Override the {@code SpanReceiver} class name provided in configuration with a new value.
-   * @return This instance
-   */
-  public SpanReceiverBuilder spanReceiverClass(final String spanReceiverClass) {
-    this.spanReceiverClass = spanReceiverClass;
-    return this;
-  }
-
-  /**
-   * Configure whether we should log errors during build().
-   * @return This instance
-   */
-  public SpanReceiverBuilder logErrors(boolean logErrors) {
-    this.logErrors = logErrors;
-    return this;
-  }
-
-  private void logError(String errorStr) {
-    if (!logErrors) {
-      return;
-    }
-    LOG.error(errorStr);
-  }
-
-  private void logError(String errorStr, Throwable e) {
-    if (!logErrors) {
-      return;
-    }
-    LOG.error(errorStr, e);
-  }
-
-  public SpanReceiver build() {
-    SpanReceiver spanReceiver = newSpanReceiver();
-    if (LOG.isTraceEnabled()) {
-      LOG.trace("Created new span receiver of type " +
-             ((spanReceiver == null) ? "(none)" :
-               spanReceiver.getClass().getName()));
-    }
-    return spanReceiver;
-  }
-
-  private SpanReceiver newSpanReceiver() {
-    if ((this.spanReceiverClass == null) ||
-        this.spanReceiverClass.isEmpty()) {
-      LOG.debug("No span receiver class specified.");
-      return null;
-    }
-    String str = spanReceiverClass;
-    if (!str.contains(".")) {
-      str = DEFAULT_PACKAGE + "." + str;
-    }
-    Class cls = null;
-    try {
-      cls = classLoader.loadClass(str);
-    } catch (ClassNotFoundException e) {
-      logError("SpanReceiverBuilder cannot find SpanReceiver class " + str +
-          ": disabling span receiver.");
-      return null;
-    }
-    Constructor<SpanReceiver> ctor = null;
-    try {
-      ctor = cls.getConstructor(HTraceConfiguration.class);
-    } catch (NoSuchMethodException e) {
-      logError("SpanReceiverBuilder cannot find a constructor for class " +
-          str + "which takes an HTraceConfiguration.  Disabling span " +
-          "receiver.");
-      return null;
-    }
-    try {
-      LOG.debug("Creating new instance of " + str + "...");
-      return ctor.newInstance(conf);
-    } catch (ReflectiveOperationException e) {
-      logError("SpanReceiverBuilder reflection error when constructing " + str +
-          ".  Disabling span receiver.", e);
-      return null;
-    } catch (Throwable e) {
-      logError("SpanReceiverBuilder constructor error when constructing " + str +
-          ".  Disabling span receiver.", e);
-      return null;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/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
deleted file mode 100644
index d0ae675..0000000
--- a/htrace-core/src/main/java/org/apache/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.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/fd889b65/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
deleted file mode 100644
index e782309..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/Trace.java
+++ /dev/null
@@ -1,223 +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.apache.htrace;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.htrace.impl.MilliSpan;
-import org.apache.htrace.impl.NeverSampler;
-import org.apache.htrace.wrappers.TraceCallable;
-import org.apache.htrace.wrappers.TraceRunnable;
-
-import java.util.concurrent.Callable;
-
-/**
- * The Trace class is the primary way to interact with the library.  It provides
- * methods to create and manipulate spans.
- *
- * A 'Span' represents a length of time.  It has many other attributes such as a
- * description, ID, and even potentially a set of key/value strings attached to
- * it.
- *
- * Each thread in your application has a single currently active currentSpan
- * associated with it.  When this is non-null, it represents the current
- * operation that the thread is doing.  Spans are NOT thread-safe, and must
- * never be used by multiple threads at once.  With care, it is possible to
- * safely pass a Span object between threads, but in most cases this is not
- * necessary.
- *
- * A 'TraceScope' can either be empty, or contain a Span.  TraceScope objects
- * implement the Java's Closeable interface.  Similar to file descriptors, they
- * must be closed after they are created.  When a TraceScope contains a Span,
- * this span is closed when the scope is closed.
- *
- * The 'startSpan' methods in this class do a few things:
- * <ul>
- *   <li>Create a new Span which has this thread's currentSpan as one of its parents.</li>
- *   <li>Set currentSpan to the new Span.</li>
- *   <li>Create a TraceSpan object to manage the new Span.</li>
- * </ul>
- *
- * Closing a TraceScope does a few things:
- * <ul>
- *   <li>It closes the span which the scope was managing.</li>
- *   <li>Set currentSpan to the previous currentSpan (which may be null).</li>
- * </ul>
- */
-public class Trace {
-  private static final Log LOG = LogFactory.getLog(Trace.class);
-
-  /**
-   * Creates a new trace scope.
-   *
-   * If this thread has a currently active trace span, the trace scope we create
-   * here will contain a new span descending from the currently active span.
-   * If there is no currently active trace span, the trace scope we create will
-   * be empty.
-   *
-   * @param description   The description field for the new span to create.
-   */
-  public static TraceScope startSpan(String description) {
-    return startSpan(description, NeverSampler.INSTANCE);
-  }
-
-  public static TraceScope startSpan(String description, SpanId parentId) {
-    if (parentId == null) {
-      return continueSpan(null);
-    }
-    Span newSpan = new MilliSpan.Builder().
-        begin(System.currentTimeMillis()).
-        end(0).
-        description(description).
-        spanId(parentId.newChildId()).
-        parents(new SpanId[] { parentId }).
-        build();
-    return continueSpan(newSpan);
-  }
-
-  /**
-   * Creates a new trace scope.
-   *
-   * If this thread has a currently active trace span, it must be the 'parent'
-   * span that you pass in here as a parameter.  The trace scope we create here
-   * will contain a new span which is a child of 'parent'.
-   *
-   * @param description   The description field for the new span to create.
-   */
-  public static TraceScope startSpan(String description, Span parent) {
-    if (parent == null) {
-      return startSpan(description);
-    }
-    Span currentSpan = currentSpan();
-    if ((currentSpan != null) && (currentSpan != parent)) {
-      Tracer.clientError("HTrace client error: thread " +
-          Thread.currentThread().getName() + " tried to start a new Span " +
-          "with parent " + parent.toString() + ", but there is already a " +
-          "currentSpan " + currentSpan);
-    }
-    return continueSpan(parent.child(description));
-  }
-
-  public static <T> TraceScope startSpan(String description, Sampler s) {
-    Span span = null;
-    if (isTracing() || s.next()) {
-      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);
-  }
-
-  /**
-   * Removes the given SpanReceiver from the list of SpanReceivers.
-   */
-  public static void removeReceiver(SpanReceiver rcvr) {
-    Tracer.getInstance().removeReceiver(rcvr);
-  }
-
-  /**
-   * Adds the given SpanReceiver to the current Tracer instance's list of
-   * SpanReceivers.
-   */
-  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(String key, String 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.
-   */
-  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.
-   *
-   * @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
-   *
-   * @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 The runnable that will have tracing info associated with it if tracing.
-   * @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/fd889b65/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
deleted file mode 100644
index ab36feb..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/TraceScope.java
+++ /dev/null
@@ -1,99 +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.apache.htrace;
-
-import java.io.Closeable;
-import java.lang.Thread;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-public class TraceScope implements Closeable {
-  private static final Log LOG = LogFactory.getLog(TraceScope.class);
-
-  /**
-   * 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() {
-    if (detached) {
-      Tracer.clientError("Tried to detach trace span " + span + " but " +
-          "it has already been detached.");
-    }
-    detached = true;
-
-    Span cur = Tracer.getInstance().currentSpan();
-    if (cur != span) {
-      Tracer.clientError("Tried to detach trace span " + span + " but " +
-          "it is not the current span for the " +
-          Thread.currentThread().getName() + " thread.  You have " +
-          "probably forgotten to close or detach " + cur);
-    } 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 (detached) {
-      return;
-    }
-    detached = true;
-    Span cur = Tracer.getInstance().currentSpan();
-    if (cur != span) {
-      Tracer.clientError("Tried to close trace span " + span + " but " +
-          "it is not the current span for the " +
-          Thread.currentThread().getName() + " thread.  You have " +
-          "probably forgotten to close or detach " + cur);
-    } else {
-      span.stop();
-      Tracer.getInstance().setCurrentSpan(savedSpan);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/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
deleted file mode 100644
index d07e1a8..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/Tracer.java
+++ /dev/null
@@ -1,130 +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.apache.htrace;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.htrace.impl.MilliSpan;
-
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * A Tracer provides the implementation for collecting and distributing Spans
- * within a process.
- */
-public class Tracer {
-  private static final Log LOG = LogFactory.getLog(Tracer.class);
-
-  static long nonZeroRandom64() {
-    long id;
-    Random random = ThreadLocalRandom.current();
-    do {
-      id = random.nextLong();
-    } while (id == 0);
-    return id;
-  }
-
-  private final List<SpanReceiver> receivers = new CopyOnWriteArrayList<SpanReceiver>();
-  private static final ThreadLocal<Span> currentSpan = new ThreadLocal<Span>() {
-    @Override
-    protected Span initialValue() {
-      return null;
-    }
-  };
-  private static final SpanId EMPTY_PARENT_ARRAY[] = new SpanId[0];
-
-  /**
-   * Log a client error, and throw an exception.
-   *
-   * @param str     The message to use in the log and the exception.
-   */
-  static void clientError(String str) {
-    LOG.error(str);
-    throw new RuntimeException(str);
-  }
-
-  /**
-   * 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.Builder().
-          begin(System.currentTimeMillis()).
-          end(0).
-          description(description).
-          parents(EMPTY_PARENT_ARRAY).
-          spanId(SpanId.fromRandom()).
-          build();
-    } 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();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/AlwaysSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/AlwaysSampler.java b/htrace-core/src/main/java/org/apache/htrace/core/AlwaysSampler.java
new file mode 100644
index 0000000..a9259bd
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/AlwaysSampler.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.core;
+
+/**
+ * A Sampler that always returns true.
+ */
+public final class AlwaysSampler implements Sampler {
+
+  public static final AlwaysSampler INSTANCE = new AlwaysSampler(null);
+
+  public AlwaysSampler(HTraceConfiguration conf) {
+  }
+
+  @Override
+  public boolean next() {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/CountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/CountSampler.java b/htrace-core/src/main/java/org/apache/htrace/core/CountSampler.java
new file mode 100644
index 0000000..10d5c98
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/CountSampler.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Sampler that returns true every N calls. Specify the frequency interval by configuring a
+ * {@code long} value for {@link #SAMPLER_FREQUENCY_CONF_KEY}.
+ */
+public class CountSampler implements Sampler {
+  public final static String SAMPLER_FREQUENCY_CONF_KEY = "sampler.frequency";
+
+  final long frequency;
+  long count = ThreadLocalRandom.current().nextLong();
+
+  public CountSampler(HTraceConfiguration conf) {
+    this.frequency = Long.parseLong(conf.get(SAMPLER_FREQUENCY_CONF_KEY), 10);
+  }
+
+  @Override
+  public boolean next() {
+    return (count++ % frequency) == 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/HTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/HTraceConfiguration.java b/htrace-core/src/main/java/org/apache/htrace/core/HTraceConfiguration.java
new file mode 100644
index 0000000..c6e445b
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/HTraceConfiguration.java
@@ -0,0 +1,109 @@
+/*
+ * 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.core;
+
+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);
+
+  private static final Map<String, String> EMPTY_MAP = new HashMap<String, String>(1);
+
+  /**
+   * An empty HTrace configuration.
+   */
+  public static final HTraceConfiguration EMPTY = fromMap(EMPTY_MAP);
+
+  /**
+   * Create an HTrace configuration from a map.
+   *
+   * @param conf    The map to create the configuration from.
+   * @return        The new configuration.
+   */
+  public static HTraceConfiguration fromMap(Map<String, String> conf) {
+    return new MapConf(conf);
+  }
+
+  public static HTraceConfiguration fromKeyValuePairs(String... pairs) {
+    if ((pairs.length % 2) != 0) {
+      throw new RuntimeException("You must specify an equal number of keys " +
+          "and values.");
+    }
+    Map<String, String> conf = new HashMap<String, String>();
+    for (int i = 0; i < pairs.length; i+=2) {
+      conf.put(pairs[i], pairs[i + 1]);
+    }
+    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/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
new file mode 100644
index 0000000..0aed846
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
@@ -0,0 +1,261 @@
+/*
+ * 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.core;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.FileSystems;
+import java.nio.file.StandardOpenOption;
+import java.util.UUID;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Writes the spans it receives to a local file.
+ */
+public class LocalFileSpanReceiver implements SpanReceiver {
+  private 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";
+  public static final int CAPACITY_DEFAULT = 5000;
+  private static ObjectWriter JSON_WRITER = new ObjectMapper().writer();
+  private final String path;
+
+  private byte[][] bufferedSpans;
+  private int bufferedSpansIndex;
+  private final ReentrantLock bufferLock = new ReentrantLock();
+
+  private final FileOutputStream stream;
+  private final FileChannel channel;
+  private final ReentrantLock channelLock = new ReentrantLock();
+  private final TracerId tracerId;
+
+  public LocalFileSpanReceiver(HTraceConfiguration conf) {
+    int capacity = conf.getInt(CAPACITY_KEY, CAPACITY_DEFAULT);
+    if (capacity < 1) {
+      throw new IllegalArgumentException(CAPACITY_KEY + " must not be " +
+          "less than 1.");
+    }
+    this.path = conf.get(PATH_KEY);
+    if (path == null || path.isEmpty()) {
+      throw new IllegalArgumentException("must configure " + PATH_KEY);
+    }
+    boolean success = false;
+    try {
+      this.stream = new FileOutputStream(path, true);
+    } catch (IOException ioe) {
+      LOG.error("Error opening " + path + ": " + ioe.getMessage());
+      throw new RuntimeException(ioe);
+    }
+    this.channel = stream.getChannel();
+    if (this.channel == null) {
+      try {
+        this.stream.close();
+      } catch (IOException e) {
+        LOG.error("Error closing " + path, e);
+      }
+      LOG.error("Failed to get channel for " + path);
+      throw new RuntimeException("Failed to get channel for " + path);
+    }
+    this.bufferedSpans = new byte[capacity][];
+    this.bufferedSpansIndex = 0;
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Created new LocalFileSpanReceiver with path = " + path +
+                ", capacity = " + capacity);
+    }
+    this.tracerId = new TracerId(conf);
+  }
+
+  /**
+   * Number of buffers to use in FileChannel#write.
+   *
+   * On UNIX, FileChannel#write uses writev-- a kernel interface that allows
+   * us to send multiple buffers at once.  This is more efficient than making a
+   * separate write call for each buffer, since it minimizes the number of
+   * transitions from userspace to kernel space.
+   */
+  private final int WRITEV_SIZE = 20;
+
+  private final static ByteBuffer newlineBuf = 
+      ByteBuffer.wrap(new byte[] { (byte)0xa });
+
+  /**
+   * Flushes a bufferedSpans array.
+   */
+  private void doFlush(byte[][] toFlush, int len) throws IOException {
+    int bidx = 0, widx = 0;
+    ByteBuffer writevBufs[] = new ByteBuffer[2 * WRITEV_SIZE];
+
+    while (true) {
+      if (widx == writevBufs.length) {
+        channel.write(writevBufs);
+        widx = 0;
+      }
+      if (bidx == len) {
+        break;
+      }
+      writevBufs[widx] = ByteBuffer.wrap(toFlush[bidx]);
+      writevBufs[widx + 1] = newlineBuf;
+      bidx++;
+      widx+=2;
+    }
+    if (widx > 0) {
+      channel.write(writevBufs, 0, widx);
+    }
+  }
+
+  @Override
+  public void receiveSpan(Span span) {
+    if (span.getTracerId().isEmpty()) {
+      span.setTracerId(tracerId.get());
+    }
+
+    // Serialize the span data into a byte[].  Note that we're not holding the
+    // lock here, to improve concurrency.
+    byte jsonBuf[] = null;
+    try {
+      jsonBuf = JSON_WRITER.writeValueAsBytes(span);
+    } catch (JsonProcessingException e) {
+        LOG.error("receiveSpan(path=" + path + ", span=" + span + "): " +
+                  "Json processing error: " + e.getMessage());
+      return;
+    }
+
+    // Grab the bufferLock and put our jsonBuf into the list of buffers to
+    // flush. 
+    byte toFlush[][] = null;
+    bufferLock.lock();
+    try {
+      if (bufferedSpans == null) {
+        LOG.debug("receiveSpan(path=" + path + ", span=" + span + "): " +
+                  "LocalFileSpanReceiver for " + path + " is closed.");
+        return;
+      }
+      bufferedSpans[bufferedSpansIndex] = jsonBuf;
+      bufferedSpansIndex++;
+      if (bufferedSpansIndex == bufferedSpans.length) {
+        // If we've hit the limit for the number of buffers to flush, 
+        // swap out the existing bufferedSpans array for a new array, and
+        // prepare to flush those spans to disk.
+        toFlush = bufferedSpans;
+        bufferedSpansIndex = 0;
+        bufferedSpans = new byte[bufferedSpans.length][];
+      }
+    } finally {
+      bufferLock.unlock();
+    }
+    if (toFlush != null) {
+      // We released the bufferLock above, to avoid blocking concurrent
+      // receiveSpan calls.  But now, we must take the channelLock, to make
+      // sure that we have sole access to the output channel.  If we did not do
+      // this, we might get interleaved output.
+      //
+      // There is a small chance that another thread doing a flush of more
+      // recent spans could get ahead of us here, and take the lock before we
+      // do.  This is ok, since spans don't have to be written out in order.
+      channelLock.lock();
+      try {
+        doFlush(toFlush, toFlush.length);
+      } catch (IOException ioe) {
+        LOG.error("Error flushing buffers to " + path + ": " +
+            ioe.getMessage());
+      } finally {
+        channelLock.unlock();
+      }
+    }
+  }
+
+  @Override
+  public void close() throws IOException {
+    byte toFlush[][] = null;
+    int numToFlush = 0;
+    bufferLock.lock();
+    try {
+      if (bufferedSpans == null) {
+        LOG.info("LocalFileSpanReceiver for " + path + " was already closed.");
+        return;
+      }
+      numToFlush = bufferedSpansIndex;
+      bufferedSpansIndex = 0;
+      toFlush = bufferedSpans;
+      bufferedSpans = null;
+    } finally {
+      bufferLock.unlock();
+    }
+    channelLock.lock();
+    try {
+      doFlush(toFlush, numToFlush);
+    } catch (IOException ioe) {
+      LOG.error("Error flushing buffers to " + path + ": " +
+          ioe.getMessage());
+    } finally {
+      try {
+        stream.close();
+      } catch (IOException e) {
+        LOG.error("Error closing stream for " + path, e);
+      }
+      channelLock.unlock();
+    }
+  }
+
+  public static String getUniqueLocalTraceFileName() {
+    String tmp = System.getProperty("java.io.tmpdir", "/tmp");
+    String nonce = null;
+    BufferedReader reader = null;
+    try {
+      // On Linux we can get a unique local file name by reading the process id
+      // out of /proc/self/stat.  (There isn't any portable way to get the
+      // process ID from Java.)
+      reader = new BufferedReader(
+          new InputStreamReader(new FileInputStream("/proc/self/stat"),
+                                "UTF-8"));
+      String line = reader.readLine();
+      if (line == null) {
+        throw new EOFException();
+      }
+      nonce = line.split(" ")[0];
+    } catch (IOException e) {
+    } finally {
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch(IOException e) {
+          LOG.warn("Exception in closing " + reader, e);
+        }
+      }
+    }
+    if (nonce == null) {
+      // If we can't use the process ID, use a random nonce.
+      nonce = UUID.randomUUID().toString();
+    }
+    return new File(tmp, nonce).getAbsolutePath();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/MilliSpan.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/MilliSpan.java b/htrace-core/src/main/java/org/apache/htrace/core/MilliSpan.java
new file mode 100644
index 0000000..49b5fbe
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/MilliSpan.java
@@ -0,0 +1,348 @@
+/*
+ * 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.core;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A Span implementation that stores its information in milliseconds since the
+ * epoch.
+ */
+@JsonDeserialize(using = MilliSpan.MilliSpanDeserializer.class)
+public class MilliSpan implements Span {
+  private static ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+  private static ObjectReader JSON_READER = OBJECT_MAPPER.reader(MilliSpan.class);
+  private static ObjectWriter JSON_WRITER = OBJECT_MAPPER.writer();
+  private static final SpanId EMPTY_PARENT_ARRAY[] = new SpanId[0];
+  private static final String EMPTY_STRING = "";
+
+  private long begin;
+  private long end;
+  private final String description;
+  private SpanId parents[];
+  private final SpanId spanId;
+  private Map<String, String> traceInfo = null;
+  private String tracerId;
+  private List<TimelineAnnotation> timeline = null;
+
+  @Override
+  public Span child(String childDescription) {
+    return new MilliSpan.Builder().
+      begin(System.currentTimeMillis()).
+      end(0).
+      description(childDescription).
+      parents(new SpanId[] {spanId}).
+      spanId(spanId.newChildId()).
+      tracerId(tracerId).
+      build();
+  }
+
+  /**
+   * The public interface for constructing a MilliSpan.
+   */
+  public static class Builder {
+    private long begin;
+    private long end;
+    private String description = EMPTY_STRING;
+    private SpanId parents[] = EMPTY_PARENT_ARRAY;
+    private SpanId spanId = SpanId.INVALID;
+    private Map<String, String> traceInfo = null;
+    private String tracerId = EMPTY_STRING;
+    private List<TimelineAnnotation> timeline = null;
+
+    public Builder() {
+    }
+
+    public Builder begin(long begin) {
+      this.begin = begin;
+      return this;
+    }
+
+    public Builder end(long end) {
+      this.end = end;
+      return this;
+    }
+
+    public Builder description(String description) {
+      this.description = description;
+      return this;
+    }
+
+    public Builder parents(SpanId parents[]) {
+      this.parents = parents;
+      return this;
+    }
+
+    public Builder parents(List<SpanId> parentList) {
+      SpanId[] parents = new SpanId[parentList.size()];
+      for (int i = 0; i < parentList.size(); i++) {
+        parents[i] = parentList.get(i);
+      }
+      this.parents = parents;
+      return this;
+    }
+
+    public Builder spanId(SpanId spanId) {
+      this.spanId = spanId;
+      return this;
+    }
+
+    public Builder traceInfo(Map<String, String> traceInfo) {
+      this.traceInfo = traceInfo.isEmpty() ? null : traceInfo;
+      return this;
+    }
+
+    public Builder tracerId(String tracerId) {
+      this.tracerId = tracerId;
+      return this;
+    }
+
+    public Builder timeline(List<TimelineAnnotation> timeline) {
+      this.timeline = timeline.isEmpty() ? null : timeline;
+      return this;
+    }
+
+    public MilliSpan build() {
+      return new MilliSpan(this);
+    }
+  }
+
+  public MilliSpan() {
+    this.begin = 0;
+    this.end = 0;
+    this.description = EMPTY_STRING;
+    this.parents = EMPTY_PARENT_ARRAY;
+    this.spanId = SpanId.INVALID;
+    this.traceInfo = null;
+    this.tracerId = EMPTY_STRING;
+    this.timeline = null;
+  }
+
+  private MilliSpan(Builder builder) {
+    this.begin = builder.begin;
+    this.end = builder.end;
+    this.description = builder.description;
+    this.parents = builder.parents;
+    this.spanId = builder.spanId;
+    this.traceInfo = builder.traceInfo;
+    this.tracerId = builder.tracerId;
+    this.timeline = builder.timeline;
+  }
+
+  @Override
+  public synchronized void stop() {
+    if (end == 0) {
+      if (begin == 0)
+        throw new IllegalStateException("Span for " + description
+            + " has not been started");
+      end = System.currentTimeMillis();
+      Tracer.getInstance().deliver(this);
+    }
+  }
+
+  protected long currentTimeMillis() {
+    return System.currentTimeMillis();
+  }
+
+  @Override
+  public synchronized boolean isRunning() {
+    return begin != 0 && end == 0;
+  }
+
+  @Override
+  public synchronized long getAccumulatedMillis() {
+    if (begin == 0)
+      return 0;
+    if (end > 0)
+      return end - begin;
+    return currentTimeMillis() - begin;
+  }
+
+  @Override
+  public String toString() {
+    return toJson();
+  }
+
+  @Override
+  public String getDescription() {
+    return description;
+  }
+
+  @Override
+  public SpanId getSpanId() {
+    return spanId;
+  }
+
+  @Override
+  public SpanId[] getParents() {
+    return parents;
+  }
+
+  @Override
+  public void setParents(SpanId[] parents) {
+    this.parents = parents;
+  }
+
+  @Override
+  public long getStartTimeMillis() {
+    return begin;
+  }
+
+  @Override
+  public long getStopTimeMillis() {
+    return end;
+  }
+
+  @Override
+  public void addKVAnnotation(String key, String value) {
+    if (traceInfo == null)
+      traceInfo = new HashMap<String, String>();
+    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<String, String> 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 getTracerId() {
+    return tracerId;
+  }
+
+  @Override
+  public void setTracerId(String tracerId) {
+    this.tracerId = tracerId;
+  }
+
+  @Override
+  public String toJson() {
+    StringWriter writer = new StringWriter();
+    try {
+      JSON_WRITER.writeValue(writer, this);
+    } catch (IOException e) {
+      // An IOException should not be possible when writing to a string.
+      throw new RuntimeException(e);
+    }
+    return writer.toString();
+  }
+
+  public static class MilliSpanDeserializer
+        extends JsonDeserializer<MilliSpan> {
+    @Override
+    public MilliSpan deserialize(JsonParser jp, DeserializationContext ctxt)
+          throws IOException, JsonProcessingException {
+      JsonNode root = jp.getCodec().readTree(jp);
+      Builder builder = new Builder();
+      JsonNode bNode = root.get("b");
+      if (bNode != null) {
+        builder.begin(bNode.asLong());
+      }
+      JsonNode eNode = root.get("e");
+      if (eNode != null) {
+        builder.end(eNode.asLong());
+      }
+      JsonNode dNode = root.get("d");
+      if (dNode != null) {
+        builder.description(dNode.asText());
+      }
+      JsonNode sNode = root.get("a");
+      if (sNode != null) {
+        builder.spanId(SpanId.fromString(sNode.asText()));
+      }
+      JsonNode rNode = root.get("r");
+      if (rNode != null) {
+        builder.tracerId(rNode.asText());
+      }
+      JsonNode parentsNode = root.get("p");
+      LinkedList<SpanId> parents = new LinkedList<SpanId>();
+      if (parentsNode != null) {
+        for (Iterator<JsonNode> iter = parentsNode.elements();
+             iter.hasNext(); ) {
+          JsonNode parentIdNode = iter.next();
+          parents.add(SpanId.fromString(parentIdNode.asText()));
+        }
+      }
+      builder.parents(parents);
+      JsonNode traceInfoNode = root.get("n");
+      if (traceInfoNode != null) {
+        HashMap<String, String> traceInfo = new HashMap<String, String>();
+        for (Iterator<String> iter = traceInfoNode.fieldNames();
+             iter.hasNext(); ) {
+          String field = iter.next();
+          traceInfo.put(field, traceInfoNode.get(field).asText());
+        }
+        builder.traceInfo(traceInfo);
+      }
+      JsonNode timelineNode = root.get("t");
+      if (timelineNode != null) {
+        LinkedList<TimelineAnnotation> timeline =
+            new LinkedList<TimelineAnnotation>();
+        for (Iterator<JsonNode> iter = timelineNode.elements();
+             iter.hasNext(); ) {
+          JsonNode ann = iter.next();
+          timeline.add(new TimelineAnnotation(ann.get("t").asLong(),
+              ann.get("m").asText()));
+        }
+        builder.timeline(timeline);
+      }
+      return builder.build();
+    }
+  }
+
+  static MilliSpan fromJson(String json) throws IOException {
+    return JSON_READER.readValue(json);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/NeverSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/NeverSampler.java b/htrace-core/src/main/java/org/apache/htrace/core/NeverSampler.java
new file mode 100644
index 0000000..65f6087
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/NeverSampler.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.core;
+
+/**
+ * A Sampler that never returns true.
+ */
+public final class NeverSampler implements Sampler {
+
+  public static final NeverSampler INSTANCE = new NeverSampler(null);
+
+  public NeverSampler(HTraceConfiguration conf) {
+  }
+
+  @Override
+  public boolean next() {
+    return false;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/NullScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/NullScope.java b/htrace-core/src/main/java/org/apache/htrace/core/NullScope.java
new file mode 100644
index 0000000..e7964cf
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/NullScope.java
@@ -0,0 +1,44 @@
+/*
+ * 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.core;
+
+/**
+ * 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 Span detach() {
+    return null;
+  }
+
+  @Override
+  public void close() {
+    return;
+  }
+
+  @Override
+  public String toString() {
+    return "NullScope";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java
new file mode 100644
index 0000000..be782ba
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java
@@ -0,0 +1,49 @@
+/*
+ * 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.core;
+
+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;
+
+  public POJOSpanReceiver(HTraceConfiguration conf) {
+    this.spans = new HashSet<Span>();
+  }
+
+  /**
+   * @return The spans this POJOSpanReceiver has received.
+   */
+  public Collection<Span> getSpans() {
+    return spans;
+  }
+
+  @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/fd889b65/htrace-core/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/ProbabilitySampler.java b/htrace-core/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
new file mode 100644
index 0000000..5bb0042
--- /dev/null
+++ b/htrace-core/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Sampler that returns true a certain percentage of the time. Specify the frequency interval by
+ * configuring a {@code double} value for {@link #SAMPLER_FRACTION_CONF_KEY}.
+ */
+public class ProbabilitySampler implements Sampler {
+  private static final Log LOG = LogFactory.getLog(ProbabilitySampler.class);
+  public final double threshold;
+  public final static String SAMPLER_FRACTION_CONF_KEY = "sampler.fraction";
+
+  public ProbabilitySampler(HTraceConfiguration conf) {
+    this.threshold = Double.parseDouble(conf.get(SAMPLER_FRACTION_CONF_KEY));
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("Created new ProbabilitySampler with threshold = " +
+                threshold + ".");
+    }
+  }
+
+  @Override
+  public boolean next() {
+    return ThreadLocalRandom.current().nextDouble() < threshold;
+  }
+}