accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bil...@apache.org
Subject [10/15] accumulo git commit: ACCUMULO-898 refactoring and deprecation of old tracing
Date Fri, 07 Nov 2014 23:05:28 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/AsyncSpanReceiver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/AsyncSpanReceiver.java b/core/src/main/java/org/apache/accumulo/core/trace/AsyncSpanReceiver.java
deleted file mode 100644
index 379302e..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/AsyncSpanReceiver.java
+++ /dev/null
@@ -1,173 +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.accumulo.core.trace;
-
-import org.apache.accumulo.trace.thrift.Annotation;
-import org.apache.accumulo.trace.thrift.RemoteSpan;
-import org.apache.log4j.Logger;
-import org.htrace.HTraceConfiguration;
-import org.htrace.Span;
-import org.htrace.SpanReceiver;
-import org.htrace.TimelineAnnotation;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.AbstractQueue;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-/**
- * Deliver Span information periodically to a destination.
- * <ul>
- * <li>Send host and service information with the span.
- * <li>Cache Destination objects by some key that can be extracted from the span.
- * <li>Can be used to queue spans up for delivery over RPC, or for saving into a file.
- * </ul>
- */
-public abstract class AsyncSpanReceiver<SpanKey,Destination> implements SpanReceiver {
-
-  private static final Logger log = Logger.getLogger(AsyncSpanReceiver.class);
-  
-  private final Map<SpanKey,Destination> clients = new HashMap<SpanKey,Destination>();
-  
-  protected String host = null;
-  protected String service = null;
-  
-  protected abstract Destination createDestination(SpanKey key) throws Exception;
-  
-  protected abstract void send(Destination resource, RemoteSpan span) throws Exception;
-  
-  protected abstract SpanKey getSpanKey(Map<ByteBuffer,ByteBuffer> data);
-  
-  Timer timer = new Timer("SpanSender", true);
-  protected final AbstractQueue<RemoteSpan> sendQueue = new ConcurrentLinkedQueue<RemoteSpan>();
-
-  public AsyncSpanReceiver() {
-    this(1000);
-  }
-
-  public AsyncSpanReceiver(long millis) {
-    timer.schedule(new TimerTask() {
-      @Override
-      public void run() {
-        try {
-          sendSpans();
-        } catch (Exception ex) {
-          log.warn("Exception sending spans to destination", ex);
-        }
-      }
-      
-    }, millis, millis);
-  }
-
-  protected void sendSpans() {
-    while (!sendQueue.isEmpty()) {
-      boolean sent = false;
-      RemoteSpan s = sendQueue.peek();
-      SpanKey dest = getSpanKey(s.data);
-      Destination client = clients.get(dest);
-      if (client == null) {
-        try {
-          clients.put(dest, createDestination(dest));
-        } catch (Exception ex) {
-          log.warn("Exception creating connection to span receiver", ex);
-        }
-      }
-      if (client != null) {
-        try {
-          send(client, s);
-          synchronized (sendQueue) {
-            sendQueue.remove();
-            sendQueue.notifyAll();
-          }
-          sent = true;
-        } catch (Exception ex) {
-          log.warn("Got error sending to " + dest + ", refreshing client", ex);
-          clients.remove(dest);
-        }
-      }
-      if (!sent)
-        break;
-    }
-  }
-
-  public static Map<ByteBuffer, ByteBuffer> convertToByteBuffers(Map<byte[], byte[]> bytesMap) {
-    if (bytesMap == null)
-      return null;
-    Map<ByteBuffer, ByteBuffer> result = new HashMap<ByteBuffer, ByteBuffer>();
-    for (Entry<byte[], byte[]> bytes : bytesMap.entrySet()) {
-      result.put(ByteBuffer.wrap(bytes.getKey()), ByteBuffer.wrap(bytes.getValue()));
-    }
-    return result;
-  }
-
-  public static List<Annotation> convertToAnnotations(List<TimelineAnnotation> annotations) {
-    if (annotations == null)
-      return null;
-    List<Annotation> result = new ArrayList<Annotation>();
-    for (TimelineAnnotation annotation : annotations) {
-      result.add(new Annotation(annotation.getTime(), annotation.getMessage()));
-    }
-    return result;
-  }
-
-  @Override
-  public void receiveSpan(Span s) {
-    Map<ByteBuffer, ByteBuffer> data = convertToByteBuffers(s.getKVAnnotations());
-    SpanKey dest = getSpanKey(data);
-    if (dest != null) {
-      List<Annotation> annotations = convertToAnnotations(s.getTimelineAnnotations());
-      sendQueue.add(new RemoteSpan(host, service==null ? s.getProcessId() : service, s.getTraceId(), s.getSpanId(), s.getParentId(),
-          s.getStartTimeMillis(), s.getStopTimeMillis(), s.getDescription(), data, annotations));
-    }
-  }
-
-  @Override
-  public void close() {
-    synchronized (sendQueue) {
-      while (!sendQueue.isEmpty()) {
-        try {
-          sendQueue.wait();
-        } catch (InterruptedException e) {
-          log.warn("flush interrupted");
-          break;
-        }
-      }
-    }
-  }
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-    host = conf.get(DistributedTrace.TRACE_HOST_PROPERTY, host);
-    if (host == null) {
-      try {
-        host = InetAddress.getLocalHost().getCanonicalHostName().toString();
-      } catch (UnknownHostException e) {
-        host = "unknown";
-      }
-    }
-    service = conf.get(DistributedTrace.TRACE_SERVICE_PROPERTY, service);
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/CountSampler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/CountSampler.java b/core/src/main/java/org/apache/accumulo/core/trace/CountSampler.java
new file mode 100644
index 0000000..df1a02a
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/CountSampler.java
@@ -0,0 +1,23 @@
+/*
+ * 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.accumulo.core.trace;
+
+public class CountSampler extends org.htrace.impl.CountSampler {
+  public CountSampler(long frequency) {
+    super(frequency);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/DistributedTrace.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/DistributedTrace.java b/core/src/main/java/org/apache/accumulo/core/trace/DistributedTrace.java
index fe9377e..5aa026b 100644
--- a/core/src/main/java/org/apache/accumulo/core/trace/DistributedTrace.java
+++ b/core/src/main/java/org/apache/accumulo/core/trace/DistributedTrace.java
@@ -27,7 +27,6 @@ import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.conf.AccumuloConfiguration;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.fate.zookeeper.ZooReader;
-import org.apache.accumulo.trace.instrument.Trace;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.util.ReflectionUtils;
 import org.apache.hadoop.util.ShutdownHookManager;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/SendSpansViaThrift.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/SendSpansViaThrift.java b/core/src/main/java/org/apache/accumulo/core/trace/SendSpansViaThrift.java
deleted file mode 100644
index 87a9378..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/SendSpansViaThrift.java
+++ /dev/null
@@ -1,97 +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.accumulo.core.trace;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import org.apache.accumulo.trace.thrift.RemoteSpan;
-import org.apache.accumulo.trace.thrift.SpanReceiver.Client;
-import org.apache.thrift.protocol.TBinaryProtocol;
-import org.apache.thrift.protocol.TProtocol;
-import org.apache.thrift.transport.TSocket;
-import org.apache.thrift.transport.TTransport;
-
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.util.Map;
-
-/**
- * Send Span data to a destination using thrift.
- */
-public class SendSpansViaThrift extends AsyncSpanReceiver<String,Client> {
-  
-  private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(SendSpansViaThrift.class);
-  
-  private static final String THRIFT = "thrift://";
-
-  public SendSpansViaThrift() {
-    super();
-  }
-
-  public SendSpansViaThrift(long millis) {
-    super(millis);
-  }
-  
-  @Override
-  protected Client createDestination(String destination) throws Exception {
-    if (destination == null)
-      return null;
-    try {
-      int portSeparatorIndex = destination.lastIndexOf(':');
-      String host = destination.substring(0, portSeparatorIndex);
-      int port = Integer.parseInt(destination.substring(portSeparatorIndex+1));
-      log.debug("Connecting to " + host + ":" + port);
-      InetSocketAddress addr = new InetSocketAddress(host, port);
-      Socket sock = new Socket();
-      sock.connect(addr);
-      TTransport transport = new TSocket(sock);
-      TProtocol prot = new TBinaryProtocol(transport);
-      return new Client(prot);
-    } catch (Exception ex) {
-      log.error(ex, ex);
-      return null;
-    }
-  }
-  
-  @Override
-  protected void send(Client client, RemoteSpan s) throws Exception {
-    if (client != null) {
-      try {
-        client.span(s);
-      } catch (Exception ex) {
-        client.getInputProtocol().getTransport().close();
-        throw ex;
-      }
-    }
-  }
-
-  private static final ByteBuffer DEST = ByteBuffer.wrap("dest".getBytes(UTF_8));
-
-  protected String getSpanKey(Map<ByteBuffer,ByteBuffer> data) {
-    String dest = new String(data.get(DEST).array());
-    if (dest != null && dest.startsWith(THRIFT)) {
-      String hostAddress = dest.substring(THRIFT.length());
-      String[] hostAddr = hostAddress.split(":", 2);
-      if (hostAddr.length == 2) {
-        return hostAddress;
-      }
-    }
-    return null;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/Span.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/Span.java b/core/src/main/java/org/apache/accumulo/core/trace/Span.java
new file mode 100644
index 0000000..3427a2e
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/Span.java
@@ -0,0 +1,148 @@
+/*
+ * 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.accumulo.core.trace;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import org.htrace.NullScope;
+import org.htrace.TimelineAnnotation;
+import org.htrace.TraceScope;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This is a wrapper for a TraceScope object, which is a wrapper for a Span and its parent.
+ * Not recommended for client use.
+ */
+public class Span implements org.htrace.Span {
+  public static final Span NULL_SPAN = new Span(NullScope.INSTANCE);
+  private TraceScope scope = null;
+  protected org.htrace.Span span = null;
+
+  public Span(TraceScope scope) {
+    this.scope = scope;
+    this.span = scope.getSpan();
+  }
+
+  public Span(org.htrace.Span span) {
+    this.span = span;
+  }
+
+  public TraceScope getScope() {
+    return scope;
+  }
+
+  public org.htrace.Span getSpan() {
+    return span;
+  }
+
+  public long traceId() {
+    return span.getTraceId();
+  }
+
+  public void data(String k, String v) {
+    if (span != null)
+      span.addKVAnnotation(k.getBytes(UTF_8), v.getBytes(UTF_8));
+  }
+
+  @Override
+  public void stop() {
+    if (scope == null) {
+      if (span != null) {
+        span.stop();
+      }
+    } else {
+      scope.close();
+    }
+  }
+
+  @Override
+  public long getStartTimeMillis() {
+    return span.getStartTimeMillis();
+  }
+
+  @Override
+  public long getStopTimeMillis() {
+    return span.getStopTimeMillis();
+  }
+
+  @Override
+  public long getAccumulatedMillis() {
+    return span.getAccumulatedMillis();
+  }
+
+  @Override
+  public boolean isRunning() {
+    return span.isRunning();
+  }
+
+  @Override
+  public String getDescription() {
+    return span.getDescription();
+  }
+
+  @Override
+  public long getSpanId() {
+    return span.getSpanId();
+  }
+
+  @Override
+  public long getTraceId() {
+    return span.getTraceId();
+  }
+
+  @Override
+  public Span child(String s) {
+    return new Span(span.child(s));
+  }
+
+  @Override
+  public long getParentId() {
+    return span.getParentId();
+  }
+
+  @Override
+  public void addKVAnnotation(byte[] k, byte[] v) {
+    span.addKVAnnotation(k, v);
+  }
+
+  @Override
+  public void addTimelineAnnotation(String s) {
+    span.addTimelineAnnotation(s);
+  }
+
+  @Override
+  public Map<byte[], byte[]> getKVAnnotations() {
+    return span.getKVAnnotations();
+  }
+
+  @Override
+  public List<TimelineAnnotation> getTimelineAnnotations() {
+    return span.getTimelineAnnotations();
+  }
+
+  @Override
+  public String getProcessId() {
+    return span.getProcessId();
+  }
+
+  @Override
+  public String toString() {
+    return span.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/SpanTree.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/SpanTree.java b/core/src/main/java/org/apache/accumulo/core/trace/SpanTree.java
deleted file mode 100644
index 772a133..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/SpanTree.java
+++ /dev/null
@@ -1,77 +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.accumulo.core.trace;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.accumulo.trace.instrument.Span;
-import org.apache.accumulo.trace.thrift.RemoteSpan;
-
-
-public class SpanTree {
-  final Map<Long,List<Long>> parentChildren = new HashMap<Long,List<Long>>();
-  public final Map<Long,RemoteSpan> nodes = new HashMap<Long,RemoteSpan>();
-  
-  public SpanTree() {}
-  
-  public void addNode(RemoteSpan span) {
-    nodes.put(span.spanId, span);
-    if (parentChildren.get(span.parentId) == null)
-      parentChildren.put(span.parentId, new ArrayList<Long>());
-    parentChildren.get(span.parentId).add(span.spanId);
-  }
-  
-  public Set<Long> visit(SpanTreeVisitor visitor) {
-    Set<Long> visited = new HashSet<Long>();
-    List<Long> root = parentChildren.get(Long.valueOf(Span.ROOT_SPAN_ID));
-    if (root == null || root.isEmpty())
-      return visited;
-    RemoteSpan rootSpan = nodes.get(root.iterator().next());
-    if (rootSpan == null)
-      return visited;
-    recurse(0, null, rootSpan, visitor, visited);
-    return visited;
-  }
-  
-  private void recurse(int level, RemoteSpan parent, RemoteSpan node, SpanTreeVisitor visitor, Set<Long> visited) {
-    // improbable case: duplicate spanId in a trace tree: prevent
-    // infinite recursion
-    if (visited.contains(node.spanId))
-      return;
-    visited.add(node.spanId);
-    List<RemoteSpan> children = new ArrayList<RemoteSpan>();
-    List<Long> childrenIds = parentChildren.get(node.spanId);
-    if (childrenIds != null) {
-      for (Long childId : childrenIds) {
-        RemoteSpan child = nodes.get(childId);
-        if (child != null) {
-          children.add(child);
-        }
-      }
-    }
-    children = TraceDump.sortByStart(children);
-    visitor.visit(level, parent, node, children);
-    for (RemoteSpan child : children) {
-      recurse(level + 1, node, child, visitor, visited);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/SpanTreeVisitor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/SpanTreeVisitor.java b/core/src/main/java/org/apache/accumulo/core/trace/SpanTreeVisitor.java
deleted file mode 100644
index 80826a0..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/SpanTreeVisitor.java
+++ /dev/null
@@ -1,26 +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.accumulo.core.trace;
-
-import java.util.Collection;
-
-import org.apache.accumulo.trace.thrift.RemoteSpan;
-
-
-public interface SpanTreeVisitor {
-  void visit(int level, RemoteSpan parent, RemoteSpan node, Collection<RemoteSpan> children);
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/Trace.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/Trace.java b/core/src/main/java/org/apache/accumulo/core/trace/Trace.java
new file mode 100644
index 0000000..fc2df17
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/Trace.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.trace;
+
+import org.apache.accumulo.core.trace.thrift.TInfo;
+import org.apache.accumulo.core.trace.wrappers.TraceRunnable;
+import org.htrace.Sampler;
+import org.htrace.TraceInfo;
+import org.htrace.wrappers.TraceProxy;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Utility class for tracing within Accumulo.  Not intended for client use!
+ *
+ */
+public class Trace {
+  /**
+   * Start a trace span with a given description.
+   */
+  public static Span on(String description) {
+    return on(description, Sampler.ALWAYS);
+  }
+
+  /**
+   * Start a trace span with a given description with the given sampler.
+   */
+  public static <T> Span on(String description, Sampler<T> sampler) {
+    return new Span(org.htrace.Trace.startSpan(description, sampler));
+  }
+
+  /**
+   * Finish the current trace.
+   */
+  public static void off() {
+    org.htrace.Span span = org.htrace.Trace.currentSpan();
+    if (span != null) {
+      span.stop();
+      org.htrace.Tracer.getInstance().continueSpan(null);
+    }
+  }
+
+  /**
+   * @deprecated since 1.7, use {@link #off()} instead
+   */
+  @Deprecated
+  public static void offNoFlush() {
+    off();
+  }
+
+  /**
+   * Returns whether tracing is currently on.
+   */
+  public static boolean isTracing() {
+    return org.htrace.Trace.isTracing();
+  }
+
+  /**
+   * Return the current span.
+   * @deprecated since 1.7 -- it is better to save the span you create in a local variable and call its methods, rather than retrieving the current span
+   */
+  @Deprecated
+  public static Span currentTrace() {
+    return new Span(org.htrace.Trace.currentSpan());
+  }
+
+  /**
+   * Get the trace id of the current span.
+   */
+  public static long currentTraceId() {
+    return org.htrace.Trace.currentSpan().getTraceId();
+  }
+
+  /**
+   * Start a new span with a given name, if already tracing.
+   */
+  public static Span start(String description) {
+    return new Span(org.htrace.Trace.startSpan(description));
+  }
+
+  /**
+   * Continue a trace by starting a new span with a given parent and description.
+   */
+  public static Span trace(TInfo info, String description) {
+    if (info.traceId == 0) {
+      return Span.NULL_SPAN;
+    }
+    TraceInfo ti = new TraceInfo(info.traceId, info.parentId);
+    return new Span(org.htrace.Trace.startSpan(description, ti));
+  }
+
+  /**
+   * Add data to the current span.
+   */
+  public static void data(String k, String v) {
+    org.htrace.Span span = org.htrace.Trace.currentSpan();
+    if (span != null)
+      span.addKVAnnotation(k.getBytes(UTF_8), v.getBytes(UTF_8));
+  }
+
+  /**
+   * Wrap a runnable in a TraceRunnable, if tracing.
+   */
+  public static Runnable wrap(Runnable runnable) {
+    if (isTracing()) {
+      return new TraceRunnable(org.htrace.Trace.currentSpan(), runnable);
+    } else {
+      return runnable;
+    }
+  }
+
+  // Wrap all calls to the given object with spans
+  public static <T> T wrapAll(T instance) {
+    return TraceProxy.trace(instance);
+  }
+
+  // Sample trace all calls to the given object
+  public static <T, V> T wrapAll(T instance, Sampler<V> dist) {
+    return TraceProxy.trace(instance, dist);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/TraceDump.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/TraceDump.java b/core/src/main/java/org/apache/accumulo/core/trace/TraceDump.java
deleted file mode 100644
index e3f9e5a..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/TraceDump.java
+++ /dev/null
@@ -1,162 +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.accumulo.core.trace;
-
-import static java.lang.Math.min;
-
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.apache.accumulo.trace.thrift.RemoteSpan;
-import org.apache.accumulo.core.cli.ClientOnDefaultTable;
-import org.apache.accumulo.core.cli.ScannerOpts;
-import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.Scanner;
-import org.apache.accumulo.core.data.Key;
-import org.apache.accumulo.core.data.Range;
-import org.apache.accumulo.core.data.Value;
-import org.apache.hadoop.io.Text;
-import org.htrace.Span;
-
-import com.beust.jcommander.Parameter;
-
-
-public class TraceDump {
-  static final long DEFAULT_TIME_IN_MILLIS = 10 * 60 * 1000l;
-  
-  static class Opts extends ClientOnDefaultTable {
-    @Parameter(names={"-l", "--list"}, description="List recent traces")
-    boolean list = false;
-    @Parameter(names={"-s", "--start"}, description="The start time of traces to display")
-    String start;
-    @Parameter(names={"-e", "--end"}, description="The end time of traces to display")
-    String end;
-    @Parameter(names={"-d", "--dump"}, description="Dump the traces")
-    boolean dump = false;
-    @Parameter(names={"-i", "--instance"}, description="URL to point to accumulo.")
-    String instance;
-    @Parameter(description=" <trace id> { <trace id> ... }")
-    List<String> traceIds = new ArrayList<String>();
-    Opts() { super("trace");}
-  }
-  
-  public static void main(String[] args) throws Exception {
-    Opts opts = new Opts();
-    ScannerOpts scanOpts = new ScannerOpts();
-    opts.parseArgs(TraceDump.class.getName(), args, scanOpts);
-    int code = 0;
-    if (opts.list) {
-      code = listSpans(opts, scanOpts);
-    }
-    if (code == 0 && opts.dump) {
-      code = dumpTrace(opts, scanOpts);
-    }
-    System.exit(code);
-  }
-  
-  public static List<RemoteSpan> sortByStart(Collection<RemoteSpan> spans) {
-    List<RemoteSpan> spanList = new ArrayList<RemoteSpan>(spans);
-    Collections.sort(spanList, new Comparator<RemoteSpan>() {
-      @Override
-      public int compare(RemoteSpan o1, RemoteSpan o2) {
-        return (int) (o1.start - o2.start);
-      }
-    });
-    return spanList;
-  }
-  
-  private static int listSpans(Opts opts, ScannerOpts scanOpts) throws Exception {
-    PrintStream out = System.out;
-    long endTime = System.currentTimeMillis();
-    long startTime = endTime - DEFAULT_TIME_IN_MILLIS;
-    Connector conn = opts.getConnector();
-    Scanner scanner = conn.createScanner(opts.getTableName(), opts.auths);
-    scanner.setBatchSize(scanOpts.scanBatchSize);
-    Range range = new Range(new Text("start:" + Long.toHexString(startTime)), new Text("start:" + Long.toHexString(endTime)));
-    scanner.setRange(range);
-    out.println("Trace            Day/Time                 (ms)  Start");
-    for (Entry<Key,Value> entry : scanner) {
-      RemoteSpan span = TraceFormatter.getRemoteSpan(entry);
-      out.println(String.format("%016x %s %5d %s", span.traceId, TraceFormatter.formatDate(new Date(span.getStart())), span.stop - span.start, span.description));
-    }
-    return 0;
-  }
-  
-  public interface Printer {
-    void print(String line);
-  }
-  
-  private static int dumpTrace(Opts opts, ScannerOpts scanOpts) throws Exception {
-    final PrintStream out = System.out;
-    Connector conn = opts.getConnector();
-    
-    int count = 0;
-    for (String traceId : opts.traceIds) {
-      Scanner scanner = conn.createScanner(opts.getTableName(), opts.auths);
-      scanner.setBatchSize(scanOpts.scanBatchSize);
-      Range range = new Range(new Text(traceId.toString()));
-      scanner.setRange(range);
-      count = printTrace(scanner, new Printer() {
-        @Override
-        public void print(String line) {
-          out.println(line);
-        }
-      });
-    }
-    return count > 0 ? 0 : 1;
-  }
-  
-  public static int printTrace(Scanner scanner, final Printer out) {
-    int count = 0;
-    SpanTree tree = new SpanTree();
-    long start = Long.MAX_VALUE;
-    for (Entry<Key,Value> entry : scanner) {
-      RemoteSpan span = TraceFormatter.getRemoteSpan(entry);
-      tree.addNode(span);
-      start = min(start, span.start);
-      if (span.parentId == Span.ROOT_SPAN_ID)
-        count++;
-    }
-    out.print(String.format("Trace started at %s", TraceFormatter.formatDate(new Date(start))));
-    out.print("Time  Start  Service@Location       Name");
-    
-    final long finalStart = start;
-    Set<Long> visited = tree.visit(new SpanTreeVisitor() {
-      @Override
-      public void visit(int level, RemoteSpan parent, RemoteSpan node, Collection<RemoteSpan> children) {
-        String fmt = "%5d+%-5d %" + (level * 2 + 1) + "s%s@%s %s";
-        out.print(String.format(fmt, node.stop - node.start, node.start - finalStart, "", node.svc, node.sender, node.description));
-      }
-    });
-    tree.nodes.keySet().removeAll(visited);
-    if (!tree.nodes.isEmpty()) {
-      out.print("Warning: the following spans are not rooted!");
-      for (RemoteSpan span : sortByStart(tree.nodes.values())) {
-        out.print(String.format("%s %s %s", Long.toHexString(span.spanId), Long.toHexString(span.parentId), span.description));
-      }
-      return -1;
-    }
-    return count;
-  }
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/TraceFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/TraceFormatter.java b/core/src/main/java/org/apache/accumulo/core/trace/TraceFormatter.java
deleted file mode 100644
index d6842df..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/TraceFormatter.java
+++ /dev/null
@@ -1,126 +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.accumulo.core.trace;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Map.Entry;
-
-import org.apache.accumulo.trace.thrift.Annotation;
-import org.apache.accumulo.trace.thrift.RemoteSpan;
-import org.apache.accumulo.core.data.Key;
-import org.apache.accumulo.core.data.Value;
-import org.apache.accumulo.core.util.format.DefaultFormatter;
-import org.apache.accumulo.core.util.format.Formatter;
-import org.apache.commons.lang.NotImplementedException;
-import org.apache.hadoop.io.Text;
-import org.apache.thrift.TException;
-import org.apache.thrift.protocol.TCompactProtocol;
-import org.apache.thrift.transport.TMemoryInputTransport;
-
-
-/**
- * A formatter than can be used in the shell to display trace information.
- * 
- */
-public class TraceFormatter implements Formatter {
-  public static final String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS";
-  // ugh... SimpleDataFormat is not thread safe
-  private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>() {
-    @Override
-    protected SimpleDateFormat initialValue() {
-      return new SimpleDateFormat(DATE_FORMAT);
-    }
-  };
-  
-  public static String formatDate(final Date date) {
-    return formatter.get().format(date);
-  }
-  
-  private final static Text SPAN_CF = new Text("span");
-  
-  private Iterator<Entry<Key,Value>> scanner;
-  private boolean printTimeStamps;
-  
-  public static RemoteSpan getRemoteSpan(Entry<Key,Value> entry) {
-    TMemoryInputTransport transport = new TMemoryInputTransport(entry.getValue().get());
-    TCompactProtocol protocol = new TCompactProtocol(transport);
-    RemoteSpan span = new RemoteSpan();
-    try {
-      span.read(protocol);
-    } catch (TException ex) {
-      throw new RuntimeException(ex);
-    }
-    return span;
-  }
-  
-  @Override
-  public boolean hasNext() {
-    return scanner.hasNext();
-  }
-  
-  @Override
-  public String next() {
-    Entry<Key,Value> next = scanner.next();
-    if (next.getKey().getColumnFamily().equals(SPAN_CF)) {
-      StringBuilder result = new StringBuilder();
-      SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
-      RemoteSpan span = getRemoteSpan(next);
-      result.append("----------------------\n");
-      result.append(String.format(" %12s:%s%n", "name", span.description));
-      result.append(String.format(" %12s:%s%n", "trace", Long.toHexString(span.traceId)));
-      result.append(String.format(" %12s:%s%n", "loc", span.svc + "@" + span.sender));
-      result.append(String.format(" %12s:%s%n", "span", Long.toHexString(span.spanId)));
-      result.append(String.format(" %12s:%s%n", "parent", Long.toHexString(span.parentId)));
-      result.append(String.format(" %12s:%s%n", "start", dateFormatter.format(span.start)));
-      result.append(String.format(" %12s:%s%n", "ms", span.stop - span.start));
-      if (span.data != null) {
-        for (Entry<ByteBuffer, ByteBuffer> entry : span.data.entrySet()) {
-          String key = new String(entry.getKey().array(), entry.getKey().arrayOffset(), entry.getKey().limit(), UTF_8);
-          String value = new String(entry.getValue().array(), entry.getValue().arrayOffset(), entry.getValue().limit(), UTF_8);
-          result.append(String.format(" %12s:%s%n", key, value));
-        }
-      }
-      if (span.annotations != null) {
-        for (Annotation annotation : span.annotations) {
-          result.append(String.format(" %12s:%s:%s%n", "annotation", annotation.getMsg(), dateFormatter.format(annotation.getTime())));
-        }
-      }
-      
-      if (printTimeStamps) {
-        result.append(String.format(" %-12s:%d%n", "timestamp", next.getKey().getTimestamp()));
-      }
-      return result.toString();
-    }
-    return DefaultFormatter.formatEntry(next, printTimeStamps);
-  }
-  
-  @Override
-  public void remove() {
-    throw new NotImplementedException();
-  }
-  
-  @Override
-  public void initialize(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
-    this.scanner = scanner.iterator();
-    this.printTimeStamps = printTimestamps;
-  }
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/Tracer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/Tracer.java b/core/src/main/java/org/apache/accumulo/core/trace/Tracer.java
new file mode 100644
index 0000000..1b42683
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/Tracer.java
@@ -0,0 +1,35 @@
+/*
+ * 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.accumulo.core.trace;
+
+import org.apache.accumulo.core.trace.thrift.TInfo;
+import org.htrace.Span;
+
+public class Tracer {
+  private static final TInfo DONT_TRACE = new TInfo(0, 0);
+
+  /**
+   * Obtain {@link org.apache.accumulo.core.trace.thrift.TInfo} for the current span.
+   */
+  public static TInfo traceInfo() {
+    Span span = org.htrace.Trace.currentSpan();
+    if (span != null) {
+      return new TInfo(span.getTraceId(), span.getSpanId());
+    }
+    return DONT_TRACE;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/ZooTraceClient.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/ZooTraceClient.java b/core/src/main/java/org/apache/accumulo/core/trace/ZooTraceClient.java
deleted file mode 100644
index f53f133..0000000
--- a/core/src/main/java/org/apache/accumulo/core/trace/ZooTraceClient.java
+++ /dev/null
@@ -1,123 +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.accumulo.core.trace;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-import org.apache.accumulo.core.Constants;
-import org.apache.accumulo.fate.zookeeper.ZooReader;
-import org.apache.log4j.Logger;
-import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.Watcher;
-import org.htrace.HTraceConfiguration;
-
-/**
- * Find a Span collector via zookeeper and push spans there via Thrift RPC
- */
-public class ZooTraceClient extends SendSpansViaThrift implements Watcher {
-  private static final Logger log = Logger.getLogger(ZooTraceClient.class);
-
-  private static final int DEFAULT_TIMEOUT = 30 * 1000;
-
-  ZooReader zoo = null;
-  String path;
-  boolean pathExists = false;
-  final Random random = new Random();
-  final List<String> hosts = new ArrayList<String>();
-
-  public ZooTraceClient() {
-    super();
-  }
-
-  public ZooTraceClient(long millis) {
-    super(millis);
-  }
-
-  @Override
-  synchronized protected String getSpanKey(Map<ByteBuffer,ByteBuffer> data) {
-    if (hosts.size() > 0) {
-      String host = hosts.get(random.nextInt(hosts.size()));
-      log.debug("sending data to " + host);
-      return host;
-    }
-    return null;
-  }
-
-  @Override
-  public void configure(HTraceConfiguration conf) {
-    super.configure(conf);
-    String keepers = conf.get(DistributedTrace.TRACER_ZK_HOST);
-    if (keepers == null)
-      throw new IllegalArgumentException("Must configure " + DistributedTrace.TRACER_ZK_HOST);
-    int timeout = conf.getInt(DistributedTrace.TRACER_ZK_TIMEOUT, DEFAULT_TIMEOUT);
-    zoo = new ZooReader(keepers, timeout);
-    path = conf.get(DistributedTrace.TRACER_ZK_PATH, Constants.ZTRACERS);
-    process(null);
-  }
-
-  @Override
-  public void process(WatchedEvent event) {
-    log.debug("Processing event for trace server zk watch");
-    try {
-      if (pathExists || zoo.exists(path)) {
-        pathExists = true;
-        updateHosts(path, zoo.getChildren(path, this));
-      } else {
-        zoo.exists(path, this);
-      }
-    } catch (Exception ex) {
-      log.error("unable to get destination hosts in zookeeper", ex);
-    }
-  }
-
-  @Override
-  protected void sendSpans() {
-    if (hosts.isEmpty()) {
-      if (!sendQueue.isEmpty()) {
-        log.error("No hosts to send data to, dropping queued spans");
-        synchronized (sendQueue) {
-          sendQueue.clear();
-          sendQueue.notifyAll();
-        }
-      }
-    } else {
-      super.sendSpans();
-    }
-  }
-
-  synchronized private void updateHosts(String path, List<String> children) {
-    log.debug("Scanning trace hosts in zookeeper: " + path);
-    try {
-      List<String> hosts = new ArrayList<String>();
-      for (String child : children) {
-        byte[] data = zoo.getData(path + "/" + child, null);
-        hosts.add(new String(data, UTF_8));
-      }
-      this.hosts.clear();
-      this.hosts.addAll(hosts);
-      log.debug("Trace hosts: " + this.hosts);
-    } catch (Exception ex) {
-      log.error("unable to get destination hosts in zookeeper", ex);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/thrift/TInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/thrift/TInfo.java b/core/src/main/java/org/apache/accumulo/core/trace/thrift/TInfo.java
new file mode 100644
index 0000000..75b0fd8
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/thrift/TInfo.java
@@ -0,0 +1,496 @@
+/*
+ * 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.
+ */
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.accumulo.core.trace.thrift;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("all") public class TInfo implements org.apache.thrift.TBase<TInfo, TInfo._Fields>, java.io.Serializable, Cloneable, Comparable<TInfo> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("TInfo");
+
+  private static final org.apache.thrift.protocol.TField TRACE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("traceId", org.apache.thrift.protocol.TType.I64, (short)1);
+  private static final org.apache.thrift.protocol.TField PARENT_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("parentId", org.apache.thrift.protocol.TType.I64, (short)2);
+
+  private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+  static {
+    schemes.put(StandardScheme.class, new TInfoStandardSchemeFactory());
+    schemes.put(TupleScheme.class, new TInfoTupleSchemeFactory());
+  }
+
+  public long traceId; // required
+  public long parentId; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  @SuppressWarnings("all") public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    TRACE_ID((short)1, "traceId"),
+    PARENT_ID((short)2, "parentId");
+
+    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // TRACE_ID
+          return TRACE_ID;
+        case 2: // PARENT_ID
+          return PARENT_ID;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  private static final int __TRACEID_ISSET_ID = 0;
+  private static final int __PARENTID_ISSET_ID = 1;
+  private byte __isset_bitfield = 0;
+  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.TRACE_ID, new org.apache.thrift.meta_data.FieldMetaData("traceId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    tmpMap.put(_Fields.PARENT_ID, new org.apache.thrift.meta_data.FieldMetaData("parentId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(TInfo.class, metaDataMap);
+  }
+
+  public TInfo() {
+  }
+
+  public TInfo(
+    long traceId,
+    long parentId)
+  {
+    this();
+    this.traceId = traceId;
+    setTraceIdIsSet(true);
+    this.parentId = parentId;
+    setParentIdIsSet(true);
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public TInfo(TInfo other) {
+    __isset_bitfield = other.__isset_bitfield;
+    this.traceId = other.traceId;
+    this.parentId = other.parentId;
+  }
+
+  public TInfo deepCopy() {
+    return new TInfo(this);
+  }
+
+  @Override
+  public void clear() {
+    setTraceIdIsSet(false);
+    this.traceId = 0;
+    setParentIdIsSet(false);
+    this.parentId = 0;
+  }
+
+  public long getTraceId() {
+    return this.traceId;
+  }
+
+  public TInfo setTraceId(long traceId) {
+    this.traceId = traceId;
+    setTraceIdIsSet(true);
+    return this;
+  }
+
+  public void unsetTraceId() {
+    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __TRACEID_ISSET_ID);
+  }
+
+  /** Returns true if field traceId is set (has been assigned a value) and false otherwise */
+  public boolean isSetTraceId() {
+    return EncodingUtils.testBit(__isset_bitfield, __TRACEID_ISSET_ID);
+  }
+
+  public void setTraceIdIsSet(boolean value) {
+    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __TRACEID_ISSET_ID, value);
+  }
+
+  public long getParentId() {
+    return this.parentId;
+  }
+
+  public TInfo setParentId(long parentId) {
+    this.parentId = parentId;
+    setParentIdIsSet(true);
+    return this;
+  }
+
+  public void unsetParentId() {
+    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PARENTID_ISSET_ID);
+  }
+
+  /** Returns true if field parentId is set (has been assigned a value) and false otherwise */
+  public boolean isSetParentId() {
+    return EncodingUtils.testBit(__isset_bitfield, __PARENTID_ISSET_ID);
+  }
+
+  public void setParentIdIsSet(boolean value) {
+    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PARENTID_ISSET_ID, value);
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case TRACE_ID:
+      if (value == null) {
+        unsetTraceId();
+      } else {
+        setTraceId((Long)value);
+      }
+      break;
+
+    case PARENT_ID:
+      if (value == null) {
+        unsetParentId();
+      } else {
+        setParentId((Long)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case TRACE_ID:
+      return Long.valueOf(getTraceId());
+
+    case PARENT_ID:
+      return Long.valueOf(getParentId());
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case TRACE_ID:
+      return isSetTraceId();
+    case PARENT_ID:
+      return isSetParentId();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof TInfo)
+      return this.equals((TInfo)that);
+    return false;
+  }
+
+  public boolean equals(TInfo that) {
+    if (that == null)
+      return false;
+
+    boolean this_present_traceId = true;
+    boolean that_present_traceId = true;
+    if (this_present_traceId || that_present_traceId) {
+      if (!(this_present_traceId && that_present_traceId))
+        return false;
+      if (this.traceId != that.traceId)
+        return false;
+    }
+
+    boolean this_present_parentId = true;
+    boolean that_present_parentId = true;
+    if (this_present_parentId || that_present_parentId) {
+      if (!(this_present_parentId && that_present_parentId))
+        return false;
+      if (this.parentId != that.parentId)
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  @Override
+  public int compareTo(TInfo other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetTraceId()).compareTo(other.isSetTraceId());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTraceId()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.traceId, other.traceId);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetParentId()).compareTo(other.isSetParentId());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetParentId()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.parentId, other.parentId);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("TInfo(");
+    boolean first = true;
+
+    sb.append("traceId:");
+    sb.append(this.traceId);
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("parentId:");
+    sb.append(this.parentId);
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+      __isset_bitfield = 0;
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class TInfoStandardSchemeFactory implements SchemeFactory {
+    public TInfoStandardScheme getScheme() {
+      return new TInfoStandardScheme();
+    }
+  }
+
+  private static class TInfoStandardScheme extends StandardScheme<TInfo> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, TInfo struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // TRACE_ID
+            if (schemeField.type == org.apache.thrift.protocol.TType.I64) {
+              struct.traceId = iprot.readI64();
+              struct.setTraceIdIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 2: // PARENT_ID
+            if (schemeField.type == org.apache.thrift.protocol.TType.I64) {
+              struct.parentId = iprot.readI64();
+              struct.setParentIdIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, TInfo struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      oprot.writeFieldBegin(TRACE_ID_FIELD_DESC);
+      oprot.writeI64(struct.traceId);
+      oprot.writeFieldEnd();
+      oprot.writeFieldBegin(PARENT_ID_FIELD_DESC);
+      oprot.writeI64(struct.parentId);
+      oprot.writeFieldEnd();
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class TInfoTupleSchemeFactory implements SchemeFactory {
+    public TInfoTupleScheme getScheme() {
+      return new TInfoTupleScheme();
+    }
+  }
+
+  private static class TInfoTupleScheme extends TupleScheme<TInfo> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, TInfo struct) throws org.apache.thrift.TException {
+      TTupleProtocol oprot = (TTupleProtocol) prot;
+      BitSet optionals = new BitSet();
+      if (struct.isSetTraceId()) {
+        optionals.set(0);
+      }
+      if (struct.isSetParentId()) {
+        optionals.set(1);
+      }
+      oprot.writeBitSet(optionals, 2);
+      if (struct.isSetTraceId()) {
+        oprot.writeI64(struct.traceId);
+      }
+      if (struct.isSetParentId()) {
+        oprot.writeI64(struct.parentId);
+      }
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, TInfo struct) throws org.apache.thrift.TException {
+      TTupleProtocol iprot = (TTupleProtocol) prot;
+      BitSet incoming = iprot.readBitSet(2);
+      if (incoming.get(0)) {
+        struct.traceId = iprot.readI64();
+        struct.setTraceIdIsSet(true);
+      }
+      if (incoming.get(1)) {
+        struct.parentId = iprot.readI64();
+        struct.setParentIdIsSet(true);
+      }
+    }
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcClientInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcClientInvocationHandler.java b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcClientInvocationHandler.java
new file mode 100644
index 0000000..8b0156d
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcClientInvocationHandler.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.accumulo.core.trace.wrappers;
+
+import org.apache.accumulo.core.trace.Span;
+import org.apache.accumulo.core.trace.Trace;
+import org.apache.accumulo.core.trace.Tracer;
+import org.apache.accumulo.core.trace.thrift.TInfo;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class RpcClientInvocationHandler<I> implements InvocationHandler {
+
+  private final I instance;
+
+  protected RpcClientInvocationHandler(final I clientInstance) {
+    instance = clientInstance;
+  }
+
+  @Override
+  public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
+    if (args == null || args.length < 1 || args[0] != null) {
+      return method.invoke(instance, args);
+    }
+    Class<?> klass = method.getParameterTypes()[0];
+    if (TInfo.class.isAssignableFrom(klass)) {
+      args[0] = Tracer.traceInfo();
+    }
+    Span span = Trace.start("client:" + method.getName());
+    try {
+      return method.invoke(instance, args);
+    } catch (InvocationTargetException ex) {
+      throw ex.getCause();
+    } finally {
+      span.stop();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcServerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcServerInvocationHandler.java b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcServerInvocationHandler.java
new file mode 100644
index 0000000..700e543
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/RpcServerInvocationHandler.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.trace.wrappers;
+
+import org.apache.accumulo.core.trace.Span;
+import org.apache.accumulo.core.trace.Trace;
+import org.apache.accumulo.core.trace.thrift.TInfo;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class RpcServerInvocationHandler<I> implements InvocationHandler {
+
+  private final I instance;
+
+  protected RpcServerInvocationHandler(final I serverInstance) {
+    instance = serverInstance;
+  }
+
+  @Override
+  public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
+    if (args == null || args.length < 1 || args[0] == null || !(args[0] instanceof TInfo)) {
+      try {
+        return method.invoke(instance, args);
+      } catch (InvocationTargetException ex) {
+        throw ex.getCause();
+      }
+    }
+    Span span = Trace.trace((TInfo) args[0], method.getName());
+    try {
+      return method.invoke(instance, args);
+    } catch (InvocationTargetException ex) {
+      throw ex.getCause();
+    } finally {
+      span.stop();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceCallable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceCallable.java b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceCallable.java
new file mode 100644
index 0000000..0d0dc56
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/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.accumulo.core.trace.wrappers;
+
+import org.htrace.Span;
+import org.htrace.Trace;
+import org.htrace.TraceScope;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Wrap a Callable with a Span that survives a change in threads.
+ * 
+ */
+public class TraceCallable<V> implements Callable<V> {
+  private final Callable<V> impl;
+  private final Span parent;
+  private final String description;
+  
+  TraceCallable(Callable<V> impl) {
+    this(Trace.currentSpan(), impl);
+  }
+  
+  TraceCallable(Span parent, Callable<V> impl) {
+    this(parent, impl, null);
+  }
+
+  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 {
+        TraceExecutorService.endThread(chunk.getSpan());
+      }
+    } 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/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceExecutorService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceExecutorService.java b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceExecutorService.java
new file mode 100644
index 0000000..5ba61bf
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceExecutorService.java
@@ -0,0 +1,123 @@
+/*
+ * 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.accumulo.core.trace.wrappers;
+
+import org.htrace.Span;
+import org.htrace.Tracer;
+
+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);
+  }
+  
+  /**
+   * Finish a given trace and set the span for the current thread to null.
+   */
+  public static void endThread(Span span) {
+    if (span != null) {
+      span.stop();
+      Tracer.getInstance().continueSpan(null);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceRunnable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceRunnable.java b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceRunnable.java
new file mode 100644
index 0000000..5723b17
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceRunnable.java
@@ -0,0 +1,79 @@
+/*
+ * 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.accumulo.core.trace.wrappers;
+
+import org.htrace.Span;
+import org.htrace.Trace;
+import org.htrace.TraceScope;
+
+/**
+ * Wrap a Runnable with a Span that survives a change in threads.
+ * 
+ */
+public class TraceRunnable implements Runnable, Comparable<TraceRunnable> {
+  
+  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 {
+        TraceExecutorService.endThread(chunk.getSpan());
+      }
+    } else {
+      runnable.run();
+    }
+  }
+
+  private String getDescription() {
+    return this.description == null ? Thread.currentThread().getName() : description;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (o instanceof TraceRunnable) {
+      return 0 == this.compareTo((TraceRunnable) o);
+    }
+    
+    return false;
+  }
+  
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  @Override
+  public int compareTo(TraceRunnable o) {
+    return ((Comparable) this.runnable).compareTo(o.runnable);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceWrap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceWrap.java b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceWrap.java
new file mode 100644
index 0000000..f675c53
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/trace/wrappers/TraceWrap.java
@@ -0,0 +1,57 @@
+/*
+ * 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.accumulo.core.trace.wrappers;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+/**
+ * To move trace data from client to server, the RPC call must be annotated to take a TInfo object as its first argument. The user can simply pass null, so long
+ * as they wrap their Client and Service objects with these functions.
+ * 
+ * <pre>
+ * Trace.on(&quot;remoteMethod&quot;);
+ * Iface c = new Client();
+ * c = TraceWrap.client(c);
+ * c.remoteMethod(null, arg2, arg3);
+ * Trace.off();
+ * </pre>
+ * 
+ * The wrapper will see the annotated method and send or re-establish the trace information.
+ * 
+ * Note that the result of these calls is a Proxy object that conforms to the basic interfaces, but is not your concrete instance.
+ * 
+ */
+public class TraceWrap {
+
+  public static <T> T service(final T instance) {
+    InvocationHandler handler = new RpcServerInvocationHandler<T>(instance);
+    return wrappedInstance(handler, instance);
+  }
+
+  public static <T> T client(final T instance) {
+    InvocationHandler handler = new RpcClientInvocationHandler<T>(instance);
+    return wrappedInstance(handler, instance);
+  }
+
+  private static <T> T wrappedInstance(final InvocationHandler handler, final T instance) {
+    @SuppressWarnings("unchecked")
+    T proxiedInstance = (T) Proxy.newProxyInstance(instance.getClass().getClassLoader(), instance.getClass().getInterfaces(), handler);
+    return proxiedInstance;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/util/NamingThreadFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/NamingThreadFactory.java b/core/src/main/java/org/apache/accumulo/core/util/NamingThreadFactory.java
index cd14c63..f90065d 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/NamingThreadFactory.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/NamingThreadFactory.java
@@ -19,7 +19,7 @@ package org.apache.accumulo.core.util;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.apache.accumulo.trace.instrument.TraceRunnable;
+import org.apache.accumulo.core.trace.wrappers.TraceRunnable;
 import org.apache.log4j.Logger;
 
 public class NamingThreadFactory implements ThreadFactory {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/java/org/apache/accumulo/core/util/ThriftUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/ThriftUtil.java b/core/src/main/java/org/apache/accumulo/core/util/ThriftUtil.java
index 0edc884..34c2e63 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/ThriftUtil.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/ThriftUtil.java
@@ -30,8 +30,8 @@ import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
 import org.apache.accumulo.core.conf.AccumuloConfiguration;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.tabletserver.thrift.TabletClientService;
-import org.apache.accumulo.trace.instrument.Span;
-import org.apache.accumulo.trace.instrument.Trace;
+import org.apache.accumulo.core.trace.Span;
+import org.apache.accumulo.core.trace.Trace;
 import org.apache.log4j.Logger;
 import org.apache.thrift.TException;
 import org.apache.thrift.TServiceClient;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/scripts/generate-thrift.sh
----------------------------------------------------------------------
diff --git a/core/src/main/scripts/generate-thrift.sh b/core/src/main/scripts/generate-thrift.sh
index 8c60cf3..050001e 100755
--- a/core/src/main/scripts/generate-thrift.sh
+++ b/core/src/main/scripts/generate-thrift.sh
@@ -27,9 +27,9 @@
 #   Use INCLUDED_MODULES=(-) in calling scripts that require no other modules
 # ========================================================================================================================
 [[ -z $REQUIRED_THRIFT_VERSION ]] && REQUIRED_THRIFT_VERSION='0.9.1'
-[[ -z $INCLUDED_MODULES ]]        && INCLUDED_MODULES=(../trace)
+[[ -z $INCLUDED_MODULES ]]        && INCLUDED_MODULES=(../server/tracer)
 [[ -z $BASE_OUTPUT_PACKAGE ]]     && BASE_OUTPUT_PACKAGE='org.apache.accumulo.core'
-[[ -z $PACKAGES_TO_GENERATE ]]    && PACKAGES_TO_GENERATE=(gc master tabletserver security client.impl data replication)
+[[ -z $PACKAGES_TO_GENERATE ]]    && PACKAGES_TO_GENERATE=(gc master tabletserver security client.impl data replication trace)
 [[ -z $BUILD_DIR ]]               && BUILD_DIR='target'
 [[ -z $LANGUAGES_TO_GENERATE ]]   && LANGUAGES_TO_GENERATE=(java)
 [[ -z $FINAL_DIR ]]               && FINAL_DIR='src/main'

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/main/thrift/trace.thrift
----------------------------------------------------------------------
diff --git a/core/src/main/thrift/trace.thrift b/core/src/main/thrift/trace.thrift
new file mode 100644
index 0000000..dc6c44d
--- /dev/null
+++ b/core/src/main/thrift/trace.thrift
@@ -0,0 +1,23 @@
+/*
+* 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.
+*/
+namespace java org.apache.accumulo.core.trace.thrift
+namespace cpp org.apache.accumulo.core.trace.thrift
+
+struct TInfo {
+   1:i64 traceId,
+   2:i64 parentId,
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/core/src/test/java/org/apache/accumulo/core/trace/PerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/trace/PerformanceTest.java b/core/src/test/java/org/apache/accumulo/core/trace/PerformanceTest.java
new file mode 100644
index 0000000..7fe5233
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/trace/PerformanceTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.accumulo.core.trace;
+
+import org.junit.Test;
+
+public class PerformanceTest {
+  
+  @Test
+  public void test() {
+    
+  }
+  
+  public static void main(String[] args) {
+    
+    long now = System.currentTimeMillis();
+    for (long i = 0; i < 1000 * 1000; i++) {
+      @SuppressWarnings("unused")
+      Long x = new Long(i);
+    }
+    System.out.println(String.format("Trivial took %d millis", System.currentTimeMillis() - now));
+    now = System.currentTimeMillis();
+    for (long i = 0; i < 1000 * 1000; i++) {
+      Span s = Trace.start("perf");
+      s.stop();
+    }
+    System.out.println(String.format("Span Loop took %d millis", System.currentTimeMillis() - now));
+    now = System.currentTimeMillis();
+    Trace.on("test");
+    for (long i = 0; i < 1000 * 1000; i++) {
+      Span s = Trace.start("perf");
+      s.stop();
+    }
+    Trace.off();
+    System.out.println(String.format("Trace took %d millis", System.currentTimeMillis() - now));
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/examples/simple/pom.xml
----------------------------------------------------------------------
diff --git a/examples/simple/pom.xml b/examples/simple/pom.xml
index 37adc00..a886c17 100644
--- a/examples/simple/pom.xml
+++ b/examples/simple/pom.xml
@@ -69,7 +69,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.accumulo</groupId>
-      <artifactId>accumulo-trace</artifactId>
+      <artifactId>accumulo-tracer</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/TraceDumpExample.java
----------------------------------------------------------------------
diff --git a/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/TraceDumpExample.java b/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/TraceDumpExample.java
index 70a23e5..8fbf5e9 100644
--- a/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/TraceDumpExample.java
+++ b/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/TraceDumpExample.java
@@ -23,8 +23,8 @@ import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.data.Range;
-import org.apache.accumulo.core.trace.TraceDump;
-import org.apache.accumulo.core.trace.TraceDump.Printer;
+import org.apache.accumulo.tracer.TraceDump;
+import org.apache.accumulo.tracer.TraceDump.Printer;
 import org.apache.hadoop.io.Text;
 
 import com.beust.jcommander.Parameter;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6b5f5ef4/minicluster/src/main/java/org/apache/accumulo/minicluster/impl/MiniAccumuloClusterImpl.java
----------------------------------------------------------------------
diff --git a/minicluster/src/main/java/org/apache/accumulo/minicluster/impl/MiniAccumuloClusterImpl.java b/minicluster/src/main/java/org/apache/accumulo/minicluster/impl/MiniAccumuloClusterImpl.java
index 3982db5..4b03609 100644
--- a/minicluster/src/main/java/org/apache/accumulo/minicluster/impl/MiniAccumuloClusterImpl.java
+++ b/minicluster/src/main/java/org/apache/accumulo/minicluster/impl/MiniAccumuloClusterImpl.java
@@ -67,6 +67,7 @@ import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.master.thrift.MasterClientService;
 import org.apache.accumulo.core.master.thrift.MasterGoalState;
 import org.apache.accumulo.core.master.thrift.MasterMonitorInfo;
+import org.apache.accumulo.core.trace.Tracer;
 import org.apache.accumulo.core.util.CachedConfiguration;
 import org.apache.accumulo.core.util.Daemon;
 import org.apache.accumulo.core.util.Pair;
@@ -88,7 +89,6 @@ import org.apache.accumulo.server.util.time.SimpleTimer;
 import org.apache.accumulo.server.zookeeper.ZooReaderWriterFactory;
 import org.apache.accumulo.start.Main;
 import org.apache.accumulo.start.classloader.vfs.MiniDFSUtil;
-import org.apache.accumulo.trace.instrument.Tracer;
 import org.apache.accumulo.tserver.TabletServer;
 import org.apache.commons.configuration.MapConfiguration;
 import org.apache.commons.io.FileUtils;


Mime
View raw message