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/09/20 06:12:05 UTC
[1/5] incubator-htrace git commit: HTRACE-259. Rename htrace-core
module to htrace-core4 to match the artifactId (stack via cmccabe)
Repository: incubator-htrace
Updated Branches:
refs/heads/master d8409ef9a -> 3c20489f8
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestTracerId.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestTracerId.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestTracerId.java
new file mode 100644
index 0000000..1e842c5
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestTracerId.java
@@ -0,0 +1,52 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+public class TestTracerId {
+ private void testTracerIdImpl(String expected, String fmt) {
+ assertEquals(expected, new TracerId(
+ HTraceConfiguration.fromKeyValuePairs(TracerId.TRACER_ID_KEY, fmt),
+ "TracerName").get());
+ }
+
+ @Test
+ public void testSimpleTracerIds() {
+ testTracerIdImpl("abc", "abc");
+ testTracerIdImpl("abc", "a\\bc");
+ testTracerIdImpl("abc", "ab\\c");
+ testTracerIdImpl("abc", "\\a\\b\\c");
+ testTracerIdImpl("a\\bc", "a\\\\bc");
+ }
+
+ @Test
+ public void testSubstitutionVariables() throws IOException {
+ testTracerIdImpl("myTracerName", "my%{tname}");
+ testTracerIdImpl(TracerId.getProcessName(), "%{pname}");
+ testTracerIdImpl("my." + TracerId.getProcessName(), "my.%{pname}");
+ testTracerIdImpl(TracerId.getBestIpString() + ".str", "%{ip}.str");
+ testTracerIdImpl("%{pname}", "\\%{pname}");
+ testTracerIdImpl("%cash%money{}", "%cash%money{}");
+ testTracerIdImpl("Foo." + Long.valueOf(TracerId.getOsPid()).toString(),
+ "Foo.%{pid}");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TraceCreator.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TraceCreator.java b/htrace-core4/src/test/java/org/apache/htrace/core/TraceCreator.java
new file mode 100644
index 0000000..b843999
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TraceCreator.java
@@ -0,0 +1,141 @@
+/*
+ * 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.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Does some stuff and traces it.
+ */
+public class TraceCreator {
+ public static final String RPC_TRACE_ROOT = "createSampleRpcTrace";
+ public static final String THREADED_TRACE_ROOT = "createThreadedTrace";
+ public static final String SIMPLE_TRACE_ROOT = "createSimpleTrace";
+
+ private final Tracer tracer;
+
+ public TraceCreator(Tracer tracer) {
+ this.tracer = tracer;
+ }
+
+ public void createSampleRpcTrace() {
+ TraceScope s = tracer.newScope(RPC_TRACE_ROOT);
+ try {
+ pretendRpcSend();
+ } finally {
+ s.close();
+ }
+ }
+
+ public void createSimpleTrace() {
+ TraceScope s = tracer.newScope(SIMPLE_TRACE_ROOT);
+ try {
+ importantWork1();
+ } finally {
+ s.close();
+ }
+ }
+
+ /**
+ * Creates the demo trace (will create different traces from call to call).
+ */
+ public void createThreadedTrace() {
+ TraceScope s = tracer.newScope(THREADED_TRACE_ROOT);
+ try {
+ Random r = ThreadLocalRandom.current();
+ int numThreads = r.nextInt(4) + 1;
+ Thread[] threads = new Thread[numThreads];
+
+ for (int i = 0; i < numThreads; i++) {
+ threads[i] = new Thread(tracer.wrap(new MyRunnable(), null));
+ }
+ for (int i = 0; i < numThreads; i++) {
+ threads[i].start();
+ }
+ for (int i = 0; i < numThreads; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ }
+ }
+ importantWork1();
+ } finally {
+ s.close();
+ }
+ }
+
+ private void importantWork1() {
+ TraceScope cur = tracer.newScope("important work 1");
+ try {
+ Thread.sleep((long) (2000 * Math.random()));
+ importantWork2();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } finally {
+ cur.close();
+ }
+ }
+
+ private void importantWork2() {
+ TraceScope cur = tracer.newScope("important work 2");
+ try {
+ Thread.sleep((long) (2000 * Math.random()));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } finally {
+ cur.close();
+ }
+ }
+
+ private class MyRunnable implements Runnable {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(750);
+ Random r = ThreadLocalRandom.current();
+ int importantNumber = 100 / r.nextInt(3);
+ System.out.println("Important number: " + importantNumber);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ } catch (ArithmeticException ae) {
+ TraceScope c = tracer.newScope("dealing with arithmetic exception.");
+ try {
+ Thread.sleep((long) (3000 * Math.random()));
+ } catch (InterruptedException ie1) {
+ Thread.currentThread().interrupt();
+ } finally {
+ c.close();
+ }
+ }
+ }
+ }
+
+ public void pretendRpcSend() {
+ Span span = tracer.getCurrentSpan();
+ pretendRpcReceiveWithTraceInfo(span.getSpanId());
+ }
+
+ public void pretendRpcReceiveWithTraceInfo(SpanId parentId) {
+ TraceScope s = tracer.newScope("received RPC", parentId);
+ try {
+ importantWork1();
+ } finally {
+ s.close();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TraceGraph.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TraceGraph.java b/htrace-core4/src/test/java/org/apache/htrace/core/TraceGraph.java
new file mode 100644
index 0000000..a06e620
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TraceGraph.java
@@ -0,0 +1,176 @@
+/*
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * Used to create the graph formed by spans.
+ */
+public class TraceGraph {
+ private static final Log LOG = LogFactory.getLog(Tracer.class);
+
+
+ public static class SpansByParent {
+ /**
+ * Compare two spans by span ID.
+ */
+ private static Comparator<Span> COMPARATOR =
+ new Comparator<Span>() {
+ @Override
+ public int compare(Span a, Span b) {
+ return a.getSpanId().compareTo(b.getSpanId());
+ }
+ };
+
+ private final TreeSet<Span> treeSet;
+
+ private final HashMap<SpanId, LinkedList<Span>> parentToSpans;
+
+ SpansByParent(Collection<Span> spans) {
+ TreeSet<Span> treeSet = new TreeSet<Span>(COMPARATOR);
+ parentToSpans = new HashMap<SpanId, LinkedList<Span>>();
+ for (Span span : spans) {
+ treeSet.add(span);
+ for (SpanId parent : span.getParents()) {
+ LinkedList<Span> list = parentToSpans.get(parent);
+ if (list == null) {
+ list = new LinkedList<Span>();
+ parentToSpans.put(parent, list);
+ }
+ list.add(span);
+ }
+ if (span.getParents().length == 0) {
+ LinkedList<Span> list = parentToSpans.get(SpanId.INVALID);
+ if (list == null) {
+ list = new LinkedList<Span>();
+ parentToSpans.put(SpanId.INVALID, list);
+ }
+ list.add(span);
+ }
+ }
+ this.treeSet = treeSet;
+ }
+
+ public List<Span> find(SpanId parentId) {
+ LinkedList<Span> spans = parentToSpans.get(parentId);
+ if (spans == null) {
+ return new LinkedList<Span>();
+ }
+ return spans;
+ }
+
+ public Iterator<Span> iterator() {
+ return Collections.unmodifiableSortedSet(treeSet).iterator();
+ }
+ }
+
+ public static class SpansByTracerId {
+ /**
+ * Compare two spans by process ID, and then by span ID.
+ */
+ private static Comparator<Span> COMPARATOR =
+ new Comparator<Span>() {
+ @Override
+ public int compare(Span a, Span b) {
+ int cmp = a.getTracerId().compareTo(b.getTracerId());
+ if (cmp != 0) {
+ return cmp;
+ }
+ return a.getSpanId().compareTo(b.getSpanId());
+ }
+ };
+
+ private final TreeSet<Span> treeSet;
+
+ SpansByTracerId(Collection<Span> spans) {
+ TreeSet<Span> treeSet = new TreeSet<Span>(COMPARATOR);
+ for (Span span : spans) {
+ treeSet.add(span);
+ }
+ this.treeSet = treeSet;
+ }
+
+ public List<Span> find(String tracerId) {
+ List<Span> spans = new ArrayList<Span>();
+ Span span = new MilliSpan.Builder().
+ spanId(SpanId.INVALID).
+ tracerId(tracerId).
+ build();
+ while (true) {
+ span = treeSet.higher(span);
+ if (span == null) {
+ break;
+ }
+ if (span.getTracerId().equals(tracerId)) {
+ break;
+ }
+ spans.add(span);
+ }
+ return spans;
+ }
+
+ public Iterator<Span> iterator() {
+ return Collections.unmodifiableSortedSet(treeSet).iterator();
+ }
+ }
+
+ private final SpansByParent spansByParent;
+ private final SpansByTracerId spansByTracerId;
+
+ /**
+ * Create a new TraceGraph
+ *
+ * @param spans The collection of spans to use to create this TraceGraph. Should
+ * have at least one root span.
+ */
+ public TraceGraph(Collection<Span> spans) {
+ this.spansByParent = new SpansByParent(spans);
+ this.spansByTracerId = new SpansByTracerId(spans);
+ }
+
+ public SpansByParent getSpansByParent() {
+ return spansByParent;
+ }
+
+ public SpansByTracerId getSpansByTracerId() {
+ return spansByTracerId;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder bld = new StringBuilder();
+ String prefix = "";
+ for (Iterator<Span> iter = spansByParent.iterator(); iter.hasNext();) {
+ Span span = iter.next();
+ bld.append(prefix).append(span.toString());
+ prefix = "\n";
+ }
+ return bld.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/util/TestUtil.java b/htrace-core4/src/test/java/org/apache/htrace/util/TestUtil.java
new file mode 100644
index 0000000..7cb4aed
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/util/TestUtil.java
@@ -0,0 +1,91 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Utilities for writing unit tests.
+ */
+public class TestUtil {
+ /**
+ * Get a dump of the stack traces of all threads.
+ */
+ public static String threadDump() {
+ StringBuilder dump = new StringBuilder();
+ Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
+ for (Map.Entry<Thread, StackTraceElement[]> e : stackTraces.entrySet()) {
+ Thread thread = e.getKey();
+ dump.append(String.format(
+ "\"%s\" %s prio=%d tid=%d %s\njava.lang.Thread.State: %s",
+ thread.getName(),
+ (thread.isDaemon() ? "daemon" : ""),
+ thread.getPriority(),
+ thread.getId(),
+ Thread.State.WAITING.equals(thread.getState()) ?
+ "in Object.wait()" : thread.getState().name().toLowerCase(),
+ Thread.State.WAITING.equals(thread.getState()) ?
+ "WAITING (on object monitor)" : thread.getState()));
+ for (StackTraceElement stackTraceElement : e.getValue()) {
+ dump.append("\n at ");
+ dump.append(stackTraceElement);
+ }
+ dump.append("\n");
+ }
+ return dump.toString();
+ }
+
+ /**
+ * A callback which returns a value of type T.
+ *
+ * TODO: remove this when we're on Java 8, in favor of
+ * java.util.function.Supplier.
+ */
+ public interface Supplier<T> {
+ T get();
+ }
+
+ /**
+ * Wait for a condition to become true for a configurable amount of time.
+ *
+ * @param check The condition to wait for.
+ * @param periodMs How often to check the condition, in milliseconds.
+ * @param timeoutMs How long to wait in total, in milliseconds.
+ */
+ public static void waitFor(Supplier<Boolean> check,
+ long periodMs, long timeoutMs)
+ throws TimeoutException, InterruptedException
+ {
+ long endNs = System.nanoTime() +
+ TimeUnit.NANOSECONDS.convert(timeoutMs, TimeUnit.MILLISECONDS);
+ while (true) {
+ boolean result = check.get();
+ if (result) {
+ return;
+ }
+ long nowNs = System.nanoTime();
+ if (nowNs >= endNs) {
+ throw new TimeoutException("Timed out waiting for test condition. " +
+ "Thread dump:\n" + threadDump());
+ }
+ Thread.sleep(periodMs);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 0e0342f..42e19ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@ language governing permissions and limitations under the License. -->
<modules>
<module>htrace-c</module>
- <module>htrace-core</module>
+ <module>htrace-core4</module>
<module>htrace-webapp</module>
<module>htrace-zipkin</module>
<module>htrace-hbase</module>
[5/5] incubator-htrace git commit: HTRACE-259. Rename htrace-core
module to htrace-core4 to match the artifactId (stack via cmccabe)
Posted by cm...@apache.org.
HTRACE-259. Rename htrace-core module to htrace-core4 to match the artifactId (stack via 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/3c20489f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-htrace/tree/3c20489f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-htrace/diff/3c20489f
Branch: refs/heads/master
Commit: 3c20489f82135341e86f1725b748320f373a4afe
Parents: d8409ef
Author: Colin P. Mccabe <cm...@apache.org>
Authored: Sat Sep 19 21:09:06 2015 -0700
Committer: Colin P. Mccabe <cm...@apache.org>
Committed: Sat Sep 19 21:11:59 2015 -0700
----------------------------------------------------------------------
htrace-core/pom.xml | 125 ----
.../org/apache/htrace/core/AlwaysSampler.java | 32 -
.../org/apache/htrace/core/CountSampler.java | 39 --
.../apache/htrace/core/HTraceConfiguration.java | 109 ---
.../htrace/core/LocalFileSpanReceiver.java | 257 -------
.../java/org/apache/htrace/core/MilliSpan.java | 347 ----------
.../org/apache/htrace/core/NeverSampler.java | 32 -
.../java/org/apache/htrace/core/NullScope.java | 69 --
.../apache/htrace/core/POJOSpanReceiver.java | 49 --
.../apache/htrace/core/ProbabilitySampler.java | 45 --
.../java/org/apache/htrace/core/Sampler.java | 131 ----
.../main/java/org/apache/htrace/core/Span.java | 193 ------
.../java/org/apache/htrace/core/SpanId.java | 146 ----
.../org/apache/htrace/core/SpanReceiver.java | 164 -----
.../htrace/core/StandardOutSpanReceiver.java | 42 --
.../apache/htrace/core/TimelineAnnotation.java | 40 --
.../org/apache/htrace/core/TraceCallable.java | 56 --
.../htrace/core/TraceExecutorService.java | 121 ----
.../org/apache/htrace/core/TraceRunnable.java | 54 --
.../java/org/apache/htrace/core/TraceScope.java | 128 ----
.../java/org/apache/htrace/core/Tracer.java | 673 -------------------
.../java/org/apache/htrace/core/TracerId.java | 294 --------
.../java/org/apache/htrace/core/TracerPool.java | 285 --------
.../org/apache/htrace/core/TestBadClient.java | 205 ------
.../apache/htrace/core/TestCountSampler.java | 41 --
.../java/org/apache/htrace/core/TestHTrace.java | 130 ----
.../htrace/core/TestHTraceConfiguration.java | 62 --
.../htrace/core/TestLocalFileSpanReceiver.java | 65 --
.../org/apache/htrace/core/TestMilliSpan.java | 145 ----
.../org/apache/htrace/core/TestNullScope.java | 43 --
.../org/apache/htrace/core/TestSampler.java | 100 ---
.../java/org/apache/htrace/core/TestSpanId.java | 72 --
.../htrace/core/TestSpanReceiverBuilder.java | 127 ----
.../org/apache/htrace/core/TestTracerId.java | 52 --
.../org/apache/htrace/core/TraceCreator.java | 141 ----
.../java/org/apache/htrace/core/TraceGraph.java | 176 -----
.../java/org/apache/htrace/util/TestUtil.java | 91 ---
htrace-core4/pom.xml | 125 ++++
.../org/apache/htrace/core/AlwaysSampler.java | 32 +
.../org/apache/htrace/core/CountSampler.java | 39 ++
.../apache/htrace/core/HTraceConfiguration.java | 109 +++
.../htrace/core/LocalFileSpanReceiver.java | 257 +++++++
.../java/org/apache/htrace/core/MilliSpan.java | 347 ++++++++++
.../org/apache/htrace/core/NeverSampler.java | 32 +
.../java/org/apache/htrace/core/NullScope.java | 69 ++
.../apache/htrace/core/POJOSpanReceiver.java | 49 ++
.../apache/htrace/core/ProbabilitySampler.java | 45 ++
.../java/org/apache/htrace/core/Sampler.java | 131 ++++
.../main/java/org/apache/htrace/core/Span.java | 193 ++++++
.../java/org/apache/htrace/core/SpanId.java | 146 ++++
.../org/apache/htrace/core/SpanReceiver.java | 164 +++++
.../htrace/core/StandardOutSpanReceiver.java | 42 ++
.../apache/htrace/core/TimelineAnnotation.java | 40 ++
.../org/apache/htrace/core/TraceCallable.java | 56 ++
.../htrace/core/TraceExecutorService.java | 121 ++++
.../org/apache/htrace/core/TraceRunnable.java | 54 ++
.../java/org/apache/htrace/core/TraceScope.java | 128 ++++
.../java/org/apache/htrace/core/Tracer.java | 673 +++++++++++++++++++
.../java/org/apache/htrace/core/TracerId.java | 294 ++++++++
.../java/org/apache/htrace/core/TracerPool.java | 285 ++++++++
.../org/apache/htrace/core/TestBadClient.java | 205 ++++++
.../apache/htrace/core/TestCountSampler.java | 41 ++
.../java/org/apache/htrace/core/TestHTrace.java | 130 ++++
.../htrace/core/TestHTraceConfiguration.java | 62 ++
.../htrace/core/TestLocalFileSpanReceiver.java | 65 ++
.../org/apache/htrace/core/TestMilliSpan.java | 145 ++++
.../org/apache/htrace/core/TestNullScope.java | 43 ++
.../org/apache/htrace/core/TestSampler.java | 100 +++
.../java/org/apache/htrace/core/TestSpanId.java | 72 ++
.../htrace/core/TestSpanReceiverBuilder.java | 127 ++++
.../org/apache/htrace/core/TestTracerId.java | 52 ++
.../org/apache/htrace/core/TraceCreator.java | 141 ++++
.../java/org/apache/htrace/core/TraceGraph.java | 176 +++++
.../java/org/apache/htrace/util/TestUtil.java | 91 +++
pom.xml | 2 +-
75 files changed, 4882 insertions(+), 4882 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/pom.xml
----------------------------------------------------------------------
diff --git a/htrace-core/pom.xml b/htrace-core/pom.xml
deleted file mode 100644
index 81f2f87..0000000
--- a/htrace-core/pom.xml
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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. -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>htrace-core4</artifactId>
- <packaging>jar</packaging>
-
- <parent>
- <artifactId>htrace</artifactId>
- <groupId>org.apache.htrace</groupId>
- <version>4.1.0-incubating-SNAPSHOT</version>
- <relativePath>..</relativePath>
- </parent>
-
- <name>htrace-core</name>
- <url>http://incubator.apache.org/projects/htrace.html</url>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- </plugin>
- <plugin>
- <artifactId>maven-javadoc-plugin</artifactId>
- </plugin>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <executions>
- <execution>
- <phase>package</phase>
- <configuration>
- <relocations>
- <relocation>
- <pattern>org.apache.commons.logging</pattern>
- <shadedPattern>org.apache.htrace.commons.logging</shadedPattern>
- </relocation>
- <relocation>
- <pattern>com.fasterxml.jackson</pattern>
- <shadedPattern>org.apache.htrace.fasterxml.jackson</shadedPattern>
- </relocation>
- </relocations>
- </configuration>
- <goals>
- <goal>shade</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-gpg-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.rat</groupId>
- <artifactId>apache-rat-plugin</artifactId>
- </plugin>
- <plugin>
- <!-- explicitly define maven-deploy-plugin after other to force exec order -->
- <artifactId>maven-deploy-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
- <dependencies>
- <!-- Global deps. -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </dependency>
- <!-- core specific deps. -->
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </dependency>
- </dependencies>
-
- <profiles>
- <profile>
- <id>dist</id>
- <build>
- <plugins>
- <plugin>
- <!--Make it so assembly:single does nothing in here-->
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <skipAssembly>true</skipAssembly>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/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
deleted file mode 100644
index 8d5a296..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/AlwaysSampler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.htrace.core;
-
-/**
- * A Sampler that always returns true.
- */
-public final class AlwaysSampler extends 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/3c20489f/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
deleted file mode 100644
index 5a838c7..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/CountSampler.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.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 extends 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/3c20489f/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
deleted file mode 100644
index c6e445b..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/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.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/3c20489f/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
deleted file mode 100644
index 69a43b1..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
+++ /dev/null
@@ -1,257 +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.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 extends 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();
-
- 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.");
- }
- String pathStr = conf.get(PATH_KEY);
- if (pathStr == null || pathStr.isEmpty()) {
- path = getUniqueLocalTraceFileName();
- } else {
- path = pathStr;
- }
- 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);
- }
- }
-
- /**
- * 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) {
- // 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/3c20489f/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
deleted file mode 100644
index 5dd6bdb..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/MilliSpan.java
+++ /dev/null
@@ -1,347 +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.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();
- }
- }
-
- 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();
- }
- }
-
- public static MilliSpan fromJson(String json) throws IOException {
- return JSON_READER.readValue(json);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/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
deleted file mode 100644
index 60cc7d2..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/NeverSampler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.htrace.core;
-
-/**
- * A Sampler that never returns true.
- */
-public final class NeverSampler extends 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/3c20489f/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
deleted file mode 100644
index fe76e46..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/NullScope.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.htrace.core;
-
-/**
- * An empty {@link TraceScope}.
- */
-class NullScope extends TraceScope {
- NullScope(Tracer tracer) {
- super(tracer, null, null);
- }
-
- @Override
- public SpanId getSpanId() {
- return SpanId.INVALID;
- }
-
- @Override
- public void detach() {
- if (detached) {
- Tracer.throwClientError("Can't detach this TraceScope because " +
- "it is already detached.");
- }
- detached = true;
- }
-
- @Override
- public void reattach() {
- if (!detached) {
- Tracer.throwClientError("Can't reattach this TraceScope because " +
- "it is not detached.");
- }
- detached = false;
- }
-
- @Override
- public void close() {
- tracer.popNullScope();
- }
-
- @Override
- public String toString() {
- return "NullScope";
- }
-
- @Override
- public void addKVAnnotation(String key, String value) {
- // do nothing
- }
-
- @Override
- public void addTimelineAnnotation(String msg) {
- // do nothing
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/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
deleted file mode 100644
index 34322fa..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.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 extends 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/3c20489f/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
deleted file mode 100644
index c0bb16c..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
+++ /dev/null
@@ -1,45 +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.core;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * 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 extends 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;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/Sampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/Sampler.java b/htrace-core/src/main/java/org/apache/htrace/core/Sampler.java
deleted file mode 100644
index af0165c..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/Sampler.java
+++ /dev/null
@@ -1,131 +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.core;
-
-import java.lang.reflect.Constructor;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * 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() > 0.5;
- * }
- * </code>
- * </pre>
- * This would trace 50% of all gets, 75% of all puts and would not trace any other requests.
- */
-public abstract class Sampler {
- /**
- * A {@link Sampler} builder. It takes a {@link Sampler} class name and
- * constructs an instance of that class, with the provided configuration.
- */
- public static class Builder {
- private static final Log LOG = LogFactory.getLog(Builder.class);
-
- private final static String DEFAULT_PACKAGE = "org.apache.htrace.core";
- private final HTraceConfiguration conf;
- private String className;
- private ClassLoader classLoader = Builder.class.getClassLoader();
-
- public Builder(HTraceConfiguration conf) {
- this.conf = conf;
- reset();
- }
-
- public Builder reset() {
- this.className = null;
- return this;
- }
-
- public Builder className(String className) {
- this.className = className;
- return this;
- }
-
- public Builder classLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- return this;
- }
-
- private void throwError(String errorStr) {
- LOG.error(errorStr);
- throw new RuntimeException(errorStr);
- }
-
- private void throwError(String errorStr, Throwable e) {
- LOG.error(errorStr, e);
- throw new RuntimeException(errorStr, e);
- }
-
- 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() {
- if (className == null || className.isEmpty()) {
- throwError("No sampler class specified.");
- }
- String str = className;
- if (!str.contains(".")) {
- str = DEFAULT_PACKAGE + "." + str;
- }
- Class cls = null;
- try {
- cls = classLoader.loadClass(str);
- } catch (ClassNotFoundException e) {
- throwError("Cannot find Sampler class " + str);
- }
- Constructor<Sampler> ctor = null;
- try {
- ctor = cls.getConstructor(HTraceConfiguration.class);
- } catch (NoSuchMethodException e) {
- throwError("Cannot find a constructor for class " +
- str + "which takes an HTraceConfiguration.");
- }
- Sampler sampler = null;
- try {
- LOG.debug("Creating new instance of " + str + "...");
- sampler = ctor.newInstance(conf);
- } catch (ReflectiveOperationException e) {
- throwError("Reflection error when constructing " +
- str + ".", e);
- } catch (Throwable t) {
- throwError("NewInstance error when constructing " +
- str + ".", t);
- }
- return sampler;
- }
- }
-
- public static final Sampler ALWAYS = AlwaysSampler.INSTANCE;
- public static final Sampler NEVER = NeverSampler.INSTANCE;
-
- public abstract boolean next();
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/Span.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/Span.java b/htrace-core/src/main/java/org/apache/htrace/core/Span.java
deleted file mode 100644
index e63d414..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/Span.java
+++ /dev/null
@@ -1,193 +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.core;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-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;
-
-/**
- * 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
- * @deprecated Since 4.0.0. Use {@link MilliSpan.Builder}
- */
- @Deprecated
- 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/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/SpanId.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/SpanId.java b/htrace-core/src/main/java/org/apache/htrace/core/SpanId.java
deleted file mode 100644
index ed31ad3..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/SpanId.java
+++ /dev/null
@@ -1,146 +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.core;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * 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/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/SpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/SpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/core/SpanReceiver.java
deleted file mode 100644
index a955ddf..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/SpanReceiver.java
+++ /dev/null
@@ -1,164 +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.core;
-
-import java.io.Closeable;
-import java.lang.reflect.Constructor;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * 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>
- */
-public abstract class SpanReceiver implements Closeable {
- /**
- * A {@link SpanReceiver} builder. It takes a {@link SpanReceiver} class name
- * and constructs an instance of that class, with the provided configuration.
- */
- public static class Builder {
- private static final Log LOG = LogFactory.getLog(Builder.class);
-
- private final static String DEFAULT_PACKAGE = "org.apache.htrace.core";
- private final HTraceConfiguration conf;
- private boolean logErrors;
- private String className;
- private ClassLoader classLoader = Builder.class.getClassLoader();
-
- public Builder(HTraceConfiguration conf) {
- this.conf = conf;
- reset();
- }
-
- /**
- * Set this builder back to defaults.
- *
- * @return this instance.
- */
- public Builder reset() {
- this.logErrors = true;
- this.className = null;
- return this;
- }
-
- public Builder className(final String className) {
- this.className = className;
- return this;
- }
-
- /**
- * Configure whether we should log errors during build().
- * @return This instance
- */
- public Builder logErrors(boolean logErrors) {
- this.logErrors = logErrors;
- return this;
- }
-
- public Builder classLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- return this;
- }
-
- private void throwError(String errorStr) {
- if (logErrors) {
- LOG.error(errorStr);
- }
- throw new RuntimeException(errorStr);
- }
-
- private void throwError(String errorStr, Throwable e) {
- if (logErrors) {
- LOG.error(errorStr, e);
- }
- throw new RuntimeException(errorStr, e);
- }
-
- public SpanReceiver build() {
- SpanReceiver spanReceiver = newSpanReceiver();
- if (LOG.isTraceEnabled()) {
- LOG.trace("Created new span receiver of type " +
- spanReceiver.getClass().getName());
- }
- return spanReceiver;
- }
-
- private SpanReceiver newSpanReceiver() {
- if ((className == null) || className.isEmpty()) {
- throwError("No span receiver class specified.");
- }
- String str = className;
- if (!str.contains(".")) {
- str = DEFAULT_PACKAGE + "." + str;
- }
- Class cls = null;
- try {
- cls = classLoader.loadClass(str);
- } catch (ClassNotFoundException e) {
- throwError("Cannot find SpanReceiver class " + str);
- }
- Constructor<SpanReceiver> ctor = null;
- try {
- ctor = cls.getConstructor(HTraceConfiguration.class);
- } catch (NoSuchMethodException e) {
- throwError("Cannot find a constructor for class " +
- str + "which takes an HTraceConfiguration.");
- }
- SpanReceiver receiver = null;
- try {
- LOG.debug("Creating new instance of " + str + "...");
- receiver = ctor.newInstance(conf);
- } catch (ReflectiveOperationException e) {
- throwError("Reflection error when constructing " +
- str + ".", e);
- } catch (Throwable t) {
- throwError("NewInstance error when constructing " +
- str + ".", t);
- }
- return receiver;
- }
- }
-
- /**
- * An ID which uniquely identifies this SpanReceiver.
- */
- private final long id;
-
- private static final AtomicLong HIGHEST_SPAN_RECEIVER_ID = new AtomicLong(0);
-
- /**
- * Get an ID uniquely identifying this SpanReceiver.
- */
- public final long getId() {
- return id;
- }
-
- protected SpanReceiver() {
- this.id = HIGHEST_SPAN_RECEIVER_ID.incrementAndGet();
- }
-
- /**
- * Called when a Span is stopped and can now be stored.
- */
- public abstract void receiveSpan(Span span);
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java b/htrace-core/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java
deleted file mode 100644
index f443ec6..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.htrace.core;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.IOException;
-
-/**
- * Used for testing. Simply prints to standard out any spans it receives.
- */
-public class StandardOutSpanReceiver extends SpanReceiver {
- private static final Log LOG = LogFactory.getLog(StandardOutSpanReceiver.class);
-
- public StandardOutSpanReceiver(HTraceConfiguration conf) {
- LOG.trace("Created new StandardOutSpanReceiver.");
- }
-
- @Override
- public void receiveSpan(Span span) {
- System.out.println(span);
- }
-
- @Override
- public void close() throws IOException {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TimelineAnnotation.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TimelineAnnotation.java b/htrace-core/src/main/java/org/apache/htrace/core/TimelineAnnotation.java
deleted file mode 100644
index 18de061..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/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.core;
-
-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/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TraceCallable.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TraceCallable.java b/htrace-core/src/main/java/org/apache/htrace/core/TraceCallable.java
deleted file mode 100644
index a0fec17..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/TraceCallable.java
+++ /dev/null
@@ -1,56 +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.core;
-
-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 Tracer tracer;
- private final Callable<V> impl;
- private final TraceScope parent;
- private final String description;
-
- TraceCallable(Tracer tracer, TraceScope parent, Callable<V> impl,
- String description) {
- this.tracer = tracer;
- this.impl = impl;
- this.parent = parent;
- if (description == null) {
- this.description = Thread.currentThread().getName();
- } else {
- this.description = description;
- }
- }
-
- @Override
- public V call() throws Exception {
- TraceScope chunk = tracer.newScope(description,
- parent.getSpan().getSpanId());
- try {
- return impl.call();
- } finally {
- chunk.close();
- }
- }
-
- public Callable<V> getImpl() {
- return impl;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TraceExecutorService.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TraceExecutorService.java b/htrace-core/src/main/java/org/apache/htrace/core/TraceExecutorService.java
deleted file mode 100644
index 81e31ea..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/TraceExecutorService.java
+++ /dev/null
@@ -1,121 +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.core;
-
-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 Tracer tracer;
- private final String scopeName;
- private final ExecutorService impl;
-
- TraceExecutorService(Tracer tracer, String scopeName,
- ExecutorService impl) {
- this.tracer = tracer;
- this.scopeName = scopeName;
- this.impl = impl;
- }
-
- @Override
- public void execute(Runnable command) {
- impl.execute(tracer.wrap(command, scopeName));
- }
-
- @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(tracer.wrap(task, scopeName));
- }
-
- @Override
- public <T> Future<T> submit(Runnable task, T result) {
- return impl.submit(tracer.wrap(task, scopeName), result);
- }
-
- @Override
- public Future<?> submit(Runnable task) {
- return impl.submit(tracer.wrap(task, scopeName));
- }
-
- 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(tracer.wrap(task, scopeName));
- }
- return result;
- }
-
- @Override
- public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
- throws InterruptedException {
- return impl.invokeAll(wrapCollection(tasks));
- }
-
- @Override
- public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
- long timeout, TimeUnit unit) throws InterruptedException {
- return impl.invokeAll(wrapCollection(tasks), timeout, unit);
- }
-
- @Override
- public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
- throws InterruptedException, ExecutionException {
- return impl.invokeAny(wrapCollection(tasks));
- }
-
- @Override
- public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout,
- TimeUnit unit) throws InterruptedException, ExecutionException,
- TimeoutException {
- return impl.invokeAny(wrapCollection(tasks), timeout, unit);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TraceRunnable.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TraceRunnable.java b/htrace-core/src/main/java/org/apache/htrace/core/TraceRunnable.java
deleted file mode 100644
index 8f98708..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/TraceRunnable.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.htrace.core;
-
-/**
- * Wrap a Runnable with a Span that survives a change in threads.
- */
-public class TraceRunnable implements Runnable {
- private final Tracer tracer;
- private final TraceScope parent;
- private final Runnable runnable;
- private final String description;
-
- public TraceRunnable(Tracer tracer, TraceScope parent,
- Runnable runnable, String description) {
- this.tracer = tracer;
- this.parent = parent;
- this.runnable = runnable;
- if (description == null) {
- this.description = Thread.currentThread().getName();
- } else {
- this.description = description;
- }
- }
-
- @Override
- public void run() {
- TraceScope chunk = tracer.newScope(description,
- parent.getSpan().getSpanId());
- try {
- runnable.run();
- } finally {
- chunk.close();
- }
- }
-
- public Runnable getRunnable() {
- return runnable;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TraceScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TraceScope.java b/htrace-core/src/main/java/org/apache/htrace/core/TraceScope.java
deleted file mode 100644
index 05a053e..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/TraceScope.java
+++ /dev/null
@@ -1,128 +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.core;
-
-import java.io.Closeable;
-
-/**
- * Create a new TraceScope at major transitions. Hosts current tracing context.
- */
-public class TraceScope implements Closeable {
- /**
- * The tracer to use for this scope.
- */
- final Tracer tracer;
-
- /**
- * The trace span for this scope, or null if the scope is closed.
- *
- * If the scope is closed, it must also be detached.
- */
- private final Span span;
-
- /**
- * The parent of this trace scope, or null if there is no parent.
- */
- private TraceScope parent;
-
- /**
- * True if this scope is detached.
- */
- boolean detached;
-
- TraceScope(Tracer tracer, Span span, TraceScope parent) {
- this.tracer = tracer;
- this.span = span;
- this.parent = parent;
- this.detached = false;
- }
-
- /**
- * Returns the span which this scope is managing.
- */
- public Span getSpan() {
- return span;
- }
-
- /**
- * Returns the span ID which this scope is managing.
- */
- public SpanId getSpanId() {
- return span.getSpanId();
- }
-
- TraceScope getParent() {
- return parent;
- }
-
- void setParent(TraceScope parent) {
- this.parent = parent;
- }
-
- /**
- * Detach this TraceScope from the current thread.
- *
- * It is OK to "leak" TraceScopes which have been detached. They will not
- * consume any resources other than a small amount of memory until they are
- * garbage collected. On the other hand, trace scopes which are still
- * attached must never be leaked.
- */
- public void detach() {
- if (detached) {
- Tracer.throwClientError("Can't detach this TraceScope because " +
- "it is already detached.");
- }
- tracer.detachScope(this);
- detached = true;
- parent = null;
- }
-
- /**
- * Attach this TraceScope to the current thread.
- */
- public void reattach() {
- if (!detached) {
- Tracer.throwClientError("Can't reattach this TraceScope because " +
- "it is not detached.");
- }
- tracer.reattachScope(this);
- detached = false;
- }
-
- /**
- * Close this TraceScope, ending the trace span it is managing.
- */
- @Override
- public void close() {
- tracer.closeScope(this);
- }
-
- public void addKVAnnotation(String key, String value) {
- span.addKVAnnotation(key, value);
- }
-
- public void addTimelineAnnotation(String msg) {
- span.addTimelineAnnotation(msg);
- }
-
- @Override
- public String toString() {
- return "TraceScope(tracerId=" + tracer.getTracerId() +
- ", span=" + span.toJson() +
- ", detached=" + detached + ")";
- }
-}
[4/5] incubator-htrace git commit: HTRACE-259. Rename htrace-core
module to htrace-core4 to match the artifactId (stack via cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/Tracer.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/Tracer.java b/htrace-core/src/main/java/org/apache/htrace/core/Tracer.java
deleted file mode 100644
index 39d972d..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/Tracer.java
+++ /dev/null
@@ -1,673 +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.core;
-
-import java.io.Closeable;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Use a Tracer instance inside a 'process' to collect and distribute its trace Spans.
- * Example processes are an HDFS DataNode or an HBase RegionServer. A Tracer instance is your
- * one-stop shop for all things tracing.
- *
- * <p>
- */
-public class Tracer implements Closeable {
- private static final Log LOG = LogFactory.getLog(Tracer.class);
-
- public final static String SPAN_RECEIVER_CLASSES_KEY = "span.receiver.classes";
- public final static String SAMPLER_CLASSES_KEY = "sampler.classes";
-
- public static class Builder {
- private String name;
- private HTraceConfiguration conf = HTraceConfiguration.EMPTY;
- private ClassLoader classLoader =
- Builder.class.getClassLoader();
- private TracerPool tracerPool = TracerPool.GLOBAL;
-
- /**
- * @deprecated Since 4.0.0. Use Constructor that takes a <code>name</code> argument instead
- */
- @Deprecated
- public Builder() {
- }
-
- public Builder(final String name) {
- name(name);
- }
-
- /**
- * @param name
- * @return This
- * @deprecated Since 4.0.0. Use Constructor that takes a <code>name</code> argument instead.
- */
- @Deprecated
- public Builder name(String name) {
- this.name = name;
- return this;
- }
-
- public Builder conf(HTraceConfiguration conf) {
- this.conf = conf;
- return this;
- }
-
- public Builder tracerPool(TracerPool tracerPool) {
- this.tracerPool = tracerPool;
- return this;
- }
-
- private void loadSamplers(List<Sampler> samplers) {
- String classNamesStr = conf.get(SAMPLER_CLASSES_KEY, "");
- List<String> classNames = getClassNamesFromConf(classNamesStr);
- StringBuilder bld = new StringBuilder();
- String prefix = "";
- for (String className : classNames) {
- try {
- Sampler sampler = new Sampler.Builder(conf).
- className(className).
- classLoader(classLoader).
- build();
- samplers.add(sampler);
- bld.append(prefix).append(className);
- prefix = ", ";
- } catch (Throwable e) {
- LOG.error("Failed to create SpanReceiver of type " + className, e);
- }
- }
- String resultString = bld.toString();
- if (resultString.isEmpty()) {
- resultString = "no samplers";
- }
- LOG.debug(SAMPLER_CLASSES_KEY + " = " + classNamesStr +
- "; loaded " + resultString);
- }
-
- private void loadSpanReceivers() {
- String classNamesStr = conf.get(SPAN_RECEIVER_CLASSES_KEY, "");
- List<String> classNames = getClassNamesFromConf(classNamesStr);
- StringBuilder bld = new StringBuilder();
- String prefix = "";
- for (String className : classNames) {
- try {
- tracerPool.loadReceiverType(className, conf, classLoader);
- bld.append(prefix).append(className);
- prefix = ", ";
- } catch (Throwable e) {
- LOG.error("Failed to create SpanReceiver of type " + className, e);
- }
- }
- String resultString = bld.toString();
- if (resultString.isEmpty()) {
- resultString = "no span receivers";
- }
- LOG.debug(SPAN_RECEIVER_CLASSES_KEY + " = " + classNamesStr +
- "; loaded " + resultString);
- }
-
- /**
- * Get a list of class names from the HTrace configuration.
- * Entries which are empty will be removed. Entries which lack a package will
- * be given the default package.
- *
- * @param classNamesStr A semicolon-separated string containing a list
- * of class names.
- * @return A list of class names.
- */
- private List<String> getClassNamesFromConf(String classNamesStr) {
- String classNames[] = classNamesStr.split(";");
- LinkedList<String> cleanedClassNames = new LinkedList<String>();
- for (String className : classNames) {
- String cleanedClassName = className.trim();
- if (!cleanedClassName.isEmpty()) {
- cleanedClassNames.add(cleanedClassName);
- }
- }
- return cleanedClassNames;
- }
-
- public Tracer build() {
- if (name == null) {
- throw new RuntimeException("You must specify a name for this Tracer.");
- }
- LinkedList<Sampler> samplers = new LinkedList<Sampler>();
- loadSamplers(samplers);
- String tracerId = new TracerId(conf, name).get();
- Tracer tracer = new Tracer(tracerId, tracerPool,
- samplers.toArray(new Sampler[samplers.size()]));
- tracerPool.addTracer(tracer);
- loadSpanReceivers();
- if (LOG.isTraceEnabled()) {
- LOG.trace("Created " + tracer + " for " + name);
- }
- return tracer;
- }
- }
-
- /**
- * The thread-specific context for this Tracer.
- *
- * This tracks the current number of trace scopes in a particular thread
- * created by this tracer. We use this to apply our samplers only for the
- * "top-level" spans.
- *
- * Note that we can't put the TraceScope objects themselves in this context,
- * since we need to be able to use TraceScopes created by other Tracers, and
- * this context is per-Tracer.
- */
- private static class ThreadContext {
- private long depth;
-
- ThreadContext() {
- this.depth = 0;
- }
-
- boolean isTopLevel() {
- return (depth == 0);
- }
-
- void pushScope() {
- depth++;
- }
-
- TraceScope pushNewScope(Tracer tracer, Span span, TraceScope parentScope) {
- TraceScope scope = new TraceScope(tracer, span, parentScope);
- threadLocalScope.set(scope);
- depth++;
- return scope;
- }
-
- void popScope() {
- if (depth <= 0) {
- throwClientError("There were more trace scopes closed than " +
- "were opened.");
- }
- depth--;
- }
- };
-
- /**
- * A subclass of ThreadLocal that starts off with a non-null initial value in
- * each thread.
- */
- private static class ThreadLocalContext extends ThreadLocal<ThreadContext> {
- @Override
- protected ThreadContext initialValue() {
- return new ThreadContext();
- }
- };
-
- /**
- * The current trace scope. This is global, so it is shared amongst all
- * libraries using HTrace.
- */
- final static ThreadLocal<TraceScope> threadLocalScope =
- new ThreadLocal<TraceScope>();
-
- /**
- * An empty array of SpanId objects. Can be used rather than constructing a
- * new object whenever we need an empty array.
- */
- private static final SpanId EMPTY_PARENT_ARRAY[] = new SpanId[0];
-
- /**
- * The tracerId.
- */
- private final String tracerId;
-
- /**
- * The TracerPool which this Tracer belongs to.
- *
- * This gets set to null after the Tracer is closed in order to catch some
- * use-after-close errors. Note that we do not synchronize access on this
- * field, since it only changes when the Tracer is closed, and the Tracer
- * should not be used after that.
- */
- private TracerPool tracerPool;
-
- /**
- * The current thread-local context for this particualr Tracer.
- */
- private final ThreadLocalContext threadContext;
-
- /**
- * The NullScope instance for this Tracer.
- */
- private final NullScope nullScope;
-
- /**
- * The currently active Samplers.
- *
- * Arrays are immutable once set. You must take the Tracer lock in order to
- * set this to a new array. If this is null, the Tracer is closed.
- */
- private volatile Sampler[] curSamplers;
-
- /**
- * Log a client error, and throw an exception.
- *
- * @param str The message to use in the log and the exception.
- */
- static void throwClientError(String str) {
- LOG.error(str);
- throw new RuntimeException(str);
- }
-
- /**
- * @return If the current thread is tracing, this function returns the Tracer that is
- * being used; otherwise, it returns null.
- */
- public static Tracer curThreadTracer() {
- TraceScope traceScope = threadLocalScope.get();
- if (traceScope == null) {
- return null;
- }
- return traceScope.tracer;
- }
-
- Tracer(String tracerId, TracerPool tracerPool, Sampler[] curSamplers) {
- this.tracerId = tracerId;
- this.tracerPool = tracerPool;
- this.threadContext = new ThreadLocalContext();
- this.nullScope = new NullScope(this);
- this.curSamplers = curSamplers;
- }
-
- public String getTracerId() {
- return tracerId;
- }
-
- private TraceScope newScopeImpl(ThreadContext context, String description) {
- Span span = new MilliSpan.Builder().
- tracerId(tracerId).
- begin(System.currentTimeMillis()).
- description(description).
- parents(EMPTY_PARENT_ARRAY).
- spanId(SpanId.fromRandom()).
- build();
- return context.pushNewScope(this, span, null);
- }
-
- private TraceScope newScopeImpl(ThreadContext context, String description,
- TraceScope parentScope) {
- SpanId parentId = parentScope.getSpan().getSpanId();
- Span span = new MilliSpan.Builder().
- tracerId(tracerId).
- begin(System.currentTimeMillis()).
- description(description).
- parents(new SpanId[] { parentId }).
- spanId(parentId.newChildId()).
- build();
- return context.pushNewScope(this, span, parentScope);
- }
-
- private TraceScope newScopeImpl(ThreadContext context, String description,
- SpanId parentId) {
- Span span = new MilliSpan.Builder().
- tracerId(tracerId).
- begin(System.currentTimeMillis()).
- description(description).
- parents(new SpanId[] { parentId }).
- spanId(parentId.newChildId()).
- build();
- return context.pushNewScope(this, span, null);
- }
-
- private TraceScope newScopeImpl(ThreadContext context, String description,
- TraceScope parentScope, SpanId secondParentId) {
- SpanId parentId = parentScope.getSpan().getSpanId();
- Span span = new MilliSpan.Builder().
- tracerId(tracerId).
- begin(System.currentTimeMillis()).
- description(description).
- parents(new SpanId[] { parentId, secondParentId }).
- spanId(parentId.newChildId()).
- build();
- return context.pushNewScope(this, span, parentScope);
- }
-
- /**
- * Create a new trace scope.
- *
- * If there are no scopes above the current scope, we will apply our
- * configured samplers. Otherwise, we will create a trace Span only if this thread
- * is already tracing, or if the passed parentID was valid.
- *
- * @param description The description of the new span to create.
- * @param parentId If this is a valid span ID, it will be added to
- * the parents of the new span we create.
- * @return The new trace scope.
- */
- public TraceScope newScope(String description, SpanId parentId) {
- TraceScope parentScope = threadLocalScope.get();
- ThreadContext context = threadContext.get();
- if (parentScope != null) {
- if (parentId.isValid() &&
- (!parentId.equals(parentScope.getSpan().getSpanId()))) {
- return newScopeImpl(context, description, parentScope, parentId);
- } else {
- return newScopeImpl(context, description, parentScope);
- }
- } else if (parentId.isValid()) {
- return newScopeImpl(context, description, parentId);
- }
- if (!context.isTopLevel()) {
- context.pushScope();
- return nullScope;
- }
- if (!sample()) {
- context.pushScope();
- return nullScope;
- }
- return newScopeImpl(context, description);
- }
-
- /**
- * Create a new trace scope.
- *
- * If there are no scopes above the current scope, we will apply our
- * configured samplers. Otherwise, we will create a trace Span only if this thread
- * is already tracing.
- * @param description The description of the new span to create.
- * @return The new trace scope.
- */
- public TraceScope newScope(String description) {
- TraceScope parentScope = threadLocalScope.get();
- ThreadContext context = threadContext.get();
- if (parentScope != null) {
- return newScopeImpl(context, description, parentScope);
- }
- if (!context.isTopLevel()) {
- context.pushScope();
- return nullScope;
- }
- if (!sample()) {
- context.pushScope();
- return nullScope;
- }
- return newScopeImpl(context, description);
- }
-
- /**
- * Return a null trace scope.
- */
- public TraceScope newNullScope() {
- ThreadContext context = threadContext.get();
- context.pushScope();
- return nullScope;
- }
-
- /**
- * Wrap the callable in a TraceCallable, if tracing.
- *
- * @return The callable provided, wrapped if tracing, 'callable' if not.
- */
- public <V> Callable<V> wrap(Callable<V> callable, String description) {
- TraceScope parentScope = threadLocalScope.get();
- if (parentScope == null) {
- return callable;
- }
- return new TraceCallable<V>(this, parentScope, callable, description);
- }
-
- /**
- * Wrap the runnable in a TraceRunnable, if tracing
- *
- * @return The runnable provided, wrapped if tracing, 'runnable' if not.
- */
- public Runnable wrap(Runnable runnable, String description) {
- TraceScope parentScope = threadLocalScope.get();
- if (parentScope == null) {
- return runnable;
- }
- return new TraceRunnable(this, parentScope, runnable, description);
- }
-
- public TraceExecutorService newTraceExecutorService(ExecutorService impl,
- String scopeName) {
- return new TraceExecutorService(this, scopeName, impl);
- }
-
- public TracerPool getTracerPool() {
- if (tracerPool == null) {
- throwClientError(toString() + " is closed.");
- }
- return tracerPool;
- }
-
- /**
- * Returns an object that will trace all calls to itself.
- */
- @SuppressWarnings("unchecked")
- <T, V> T createProxy(final T instance) {
- final Tracer tracer = this;
- InvocationHandler handler = new InvocationHandler() {
- @Override
- public Object invoke(Object obj, Method method, Object[] args)
- throws Throwable {
- TraceScope scope = tracer.newScope(method.getName());
- try {
- return method.invoke(instance, args);
- } catch (Throwable ex) {
- ex.printStackTrace();
- throw ex;
- } finally {
- scope.close();
- }
- }
- };
- return (T) Proxy.newProxyInstance(instance.getClass().getClassLoader(),
- instance.getClass().getInterfaces(), handler);
- }
-
- /**
- * Return true if we should create a new top-level span.
- *
- * We will create the span if any configured sampler returns true.
- */
- private boolean sample() {
- Sampler[] samplers = curSamplers;
- for (Sampler sampler : samplers) {
- if (sampler.next()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns an array of all the current Samplers.
- *
- * Note that if the current Samplers change, those changes will not be
- * reflected in this array. In other words, this array may be stale.
- */
- public Sampler[] getSamplers() {
- return curSamplers;
- }
-
- /**
- * Add a new Sampler.
- *
- * @param sampler The new sampler to add.
- * You cannot add a particular Sampler object more
- * than once. You may add multiple Sampler objects
- * of the same type, although this is not recommended.
- *
- * @return True if the sampler was added; false if it already had
- * been added earlier.
- */
- public synchronized boolean addSampler(Sampler sampler) {
- if (tracerPool == null) {
- throwClientError(toString() + " is closed.");
- }
- Sampler[] samplers = curSamplers;
- for (int i = 0; i < samplers.length; i++) {
- if (samplers[i] == sampler) {
- return false;
- }
- }
- Sampler[] newSamplers =
- Arrays.copyOf(samplers, samplers.length + 1);
- newSamplers[samplers.length] = sampler;
- curSamplers = newSamplers;
- return true;
- }
-
- /**
- * Remove a SpanReceiver.
- *
- * @param sampler The sampler to remove.
- */
- public synchronized boolean removeSampler(Sampler sampler) {
- if (tracerPool == null) {
- throwClientError(toString() + " is closed.");
- }
- Sampler[] samplers = curSamplers;
- for (int i = 0; i < samplers.length; i++) {
- if (samplers[i] == sampler) {
- Sampler[] newSamplers = new Sampler[samplers.length - 1];
- System.arraycopy(samplers, 0, newSamplers, 0, i);
- System.arraycopy(samplers, i + 1, newSamplers, i,
- samplers.length - i - 1);
- curSamplers = newSamplers;
- return true;
- }
- }
- return false;
- }
-
- void detachScope(TraceScope scope) {
- TraceScope curScope = threadLocalScope.get();
- if (curScope != scope) {
- throwClientError("Can't detach TraceScope for " +
- scope.getSpan().toJson() + " because it is not the current " +
- "TraceScope in thread " + Thread.currentThread().getName());
- }
- ThreadContext context = threadContext.get();
- context.popScope();
- threadLocalScope.set(scope.getParent());
- }
-
- void reattachScope(TraceScope scope) {
- TraceScope parent = threadLocalScope.get();
- Tracer.threadLocalScope.set(scope);
- ThreadContext context = threadContext.get();
- context.pushScope();
- scope.setParent(parent);
- }
-
- void closeScope(TraceScope scope) {
- TraceScope curScope = threadLocalScope.get();
- if (curScope != scope) {
- throwClientError("Can't close TraceScope for " +
- scope.getSpan().toJson() + " because it is not the current " +
- "TraceScope in thread " + Thread.currentThread().getName());
- }
- if (tracerPool == null) {
- throwClientError(toString() + " is closed.");
- }
- SpanReceiver[] receivers = tracerPool.getReceivers();
- if (receivers == null) {
- throwClientError(toString() + " is closed.");
- }
- ThreadContext context = threadContext.get();
- context.popScope();
- threadLocalScope.set(scope.getParent());
- scope.setParent(null);
- Span span = scope.getSpan();
- span.stop();
- for (SpanReceiver receiver : receivers) {
- receiver.receiveSpan(span);
- }
- }
-
- void popNullScope() {
- TraceScope curScope = threadLocalScope.get();
- if (curScope != null) {
- throwClientError("Attempted to close an empty scope, but it was not " +
- "the current thread scope in thread " +
- Thread.currentThread().getName());
- }
- ThreadContext context = threadContext.get();
- context.popScope();
- }
-
- public static Span getCurrentSpan() {
- TraceScope curScope = threadLocalScope.get();
- if (curScope == null) {
- return null;
- } else {
- return curScope.getSpan();
- }
- }
-
- public static SpanId getCurrentSpanId() {
- TraceScope curScope = threadLocalScope.get();
- if (curScope == null) {
- return SpanId.INVALID;
- } else {
- return curScope.getSpan().getSpanId();
- }
- }
-
- @Override
- public synchronized void close() {
- if (tracerPool == null) {
- return;
- }
- curSamplers = new Sampler[0];
- tracerPool.removeTracer(this);
- }
-
- /**
- * Get the hash code of a Tracer object.
- *
- * This hash code is based on object identity.
- * This is used in TracerPool to create a hash table of Tracers.
- */
- @Override
- public int hashCode() {
- return System.identityHashCode(this);
- }
-
- /**
- * Compare two tracer objects.
- *
- * Tracer objects are always compared by object equality.
- * This is used in TracerPool to create a hash table of Tracers.
- */
- @Override
- public boolean equals(Object other) {
- return (this == other);
- }
-
- @Override
- public String toString() {
- return "Tracer(" + tracerId + ")";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TracerId.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TracerId.java b/htrace-core/src/main/java/org/apache/htrace/core/TracerId.java
deleted file mode 100644
index da482fe..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/TracerId.java
+++ /dev/null
@@ -1,294 +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.core;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Enumeration;
-import java.util.Locale;
-import java.util.TreeSet;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * The HTrace tracer ID.<p/>
- *
- * HTrace tracer IDs are created from format strings.
- * Format strings contain variables which the TracerId class will
- * replace with the correct values at runtime.<p/>
- *
- * <ul>
- * <li>%{tname}: the tracer name supplied when creating the Tracer.</li>
- * <li>%{pname}: the process name obtained from the JVM.</li>
- * <li>%{ip}: will be replaced with an ip address.</li>
- * <li>%{pid}: the numerical process ID from the operating system.</li>
- * </ul><p/>
- *
- * For example, the string "%{pname}/%{ip}" will be replaced with something
- * like: DataNode/192.168.0.1, assuming that the process' name is DataNode
- * and its IP address is 192.168.0.1.<p/>
- *
- * ID strings can contain backslashes as escapes.
- * For example, "\a" will map to "a". "\%{ip}" will map to the literal
- * string "%{ip}", not the IP address. A backslash itself can be escaped by a
- * preceding backslash.
- */
-public final class TracerId {
- private static final Log LOG = LogFactory.getLog(TracerId.class);
-
- /**
- * The configuration key to use for process id
- */
- public static final String TRACER_ID_KEY = "tracer.id";
-
- /**
- * The default tracer ID to use if no other ID is configured.
- */
- private static final String DEFAULT_TRACER_ID = "%{tname}/%{ip}";
-
- private final String tracerName;
-
- private final String tracerId;
-
- public TracerId(HTraceConfiguration conf, String tracerName) {
- this.tracerName = tracerName;
- String fmt = conf.get(TRACER_ID_KEY, DEFAULT_TRACER_ID);
- StringBuilder bld = new StringBuilder();
- StringBuilder varBld = null;
- boolean escaping = false;
- int varSeen = 0;
- for (int i = 0, len = fmt.length() ; i < len; i++) {
- char c = fmt.charAt(i);
- if (c == '\\') {
- if (!escaping) {
- escaping = true;
- continue;
- }
- }
- switch (varSeen) {
- case 0:
- if (c == '%') {
- if (!escaping) {
- varSeen = 1;
- continue;
- }
- }
- escaping = false;
- varSeen = 0;
- bld.append(c);
- break;
- case 1:
- if (c == '{') {
- if (!escaping) {
- varSeen = 2;
- varBld = new StringBuilder();
- continue;
- }
- }
- escaping = false;
- varSeen = 0;
- bld.append("%").append(c);
- break;
- default:
- if (c == '}') {
- if (!escaping) {
- String var = varBld.toString();
- bld.append(processShellVar(var));
- varBld = null;
- varSeen = 0;
- continue;
- }
- }
- escaping = false;
- varBld.append(c);
- varSeen++;
- break;
- }
- }
- if (varSeen > 0) {
- LOG.warn("Unterminated process ID substitution variable at the end " +
- "of format string " + fmt);
- }
- this.tracerId = bld.toString();
- if (LOG.isTraceEnabled()) {
- LOG.trace("ProcessID(fmt=" + fmt + "): computed process ID of \"" +
- this.tracerId + "\"");
- }
- }
-
- private String processShellVar(String var) {
- if (var.equals("tname")) {
- return tracerName;
- } else if (var.equals("pname")) {
- return getProcessName();
- } else if (var.equals("ip")) {
- return getBestIpString();
- } else if (var.equals("pid")) {
- return Long.valueOf(getOsPid()).toString();
- } else {
- LOG.warn("unknown ProcessID variable " + var);
- return "";
- }
- }
-
- static String getProcessName() {
- String cmdLine = System.getProperty("sun.java.command");
- if (cmdLine != null && !cmdLine.isEmpty()) {
- String fullClassName = cmdLine.split("\\s+")[0];
- String[] classParts = fullClassName.split("\\.");
- cmdLine = classParts[classParts.length - 1];
- }
- return (cmdLine == null || cmdLine.isEmpty()) ? "Unknown" : cmdLine;
- }
-
- /**
- * Get the best IP address that represents this node.<p/>
- *
- * This is complicated since nodes can have multiple network interfaces,
- * and each network interface can have multiple IP addresses. What we're
- * looking for here is an IP address that will serve to identify this node
- * to HTrace. So we prefer site-local addresess (i.e. private ones on the
- * LAN) to publicly routable interfaces. If there are multiple addresses
- * to choose from, we select the one which comes first in textual sort
- * order. This should ensure that we at least consistently call each node
- * by a single name.
- */
- static String getBestIpString() {
- Enumeration<NetworkInterface> ifaces;
- try {
- ifaces = NetworkInterface.getNetworkInterfaces();
- } catch (SocketException e) {
- LOG.error("Error getting network interfaces", e);
- return "127.0.0.1";
- }
- TreeSet<String> siteLocalCandidates = new TreeSet<String>();
- TreeSet<String> candidates = new TreeSet<String>();
- while (ifaces.hasMoreElements()) {
- NetworkInterface iface = ifaces.nextElement();
- for (Enumeration<InetAddress> addrs =
- iface.getInetAddresses(); addrs.hasMoreElements();) {
- InetAddress addr = addrs.nextElement();
- if (!addr.isLoopbackAddress()) {
- if (addr.isSiteLocalAddress()) {
- siteLocalCandidates.add(addr.getHostAddress());
- } else {
- candidates.add(addr.getHostAddress());
- }
- }
- }
- }
- if (!siteLocalCandidates.isEmpty()) {
- return siteLocalCandidates.first();
- }
- if (!candidates.isEmpty()) {
- return candidates.first();
- }
- return "127.0.0.1";
- }
-
- /**
- * Get the process id from the operating system.<p/>
- *
- * Unfortunately, there is no simple method to get the process id in Java.
- * The approach we take here is to use the shell method (see
- * {TracerId#getOsPidFromShellPpid}) unless we are on Windows, where the
- * shell is not available. On Windows, we use
- * {TracerId#getOsPidFromManagementFactory}, which depends on some
- * undocumented features of the JVM, but which doesn't require a shell.
- */
- static long getOsPid() {
- if ((System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH)).
- contains("windows")) {
- return getOsPidFromManagementFactory();
- } else {
- return getOsPidFromShellPpid();
- }
- }
-
- /**
- * Get the process ID by executing a shell and printing the PPID (parent
- * process ID).<p/>
- *
- * This method of getting the process ID doesn't depend on any undocumented
- * features of the virtual machine, and should work on almost any UNIX
- * operating system.
- */
- private static long getOsPidFromShellPpid() {
- Process p = null;
- StringBuilder sb = new StringBuilder();
- try {
- p = new ProcessBuilder("/usr/bin/env", "sh", "-c", "echo $PPID").
- redirectErrorStream(true).start();
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(p.getInputStream()));
- String line = "";
- while ((line = reader.readLine()) != null) {
- sb.append(line.trim());
- }
- int exitVal = p.waitFor();
- if (exitVal != 0) {
- throw new IOException("Process exited with error code " +
- Integer.valueOf(exitVal).toString());
- }
- } catch (InterruptedException e) {
- LOG.error("Interrupted while getting operating system pid from " +
- "the shell.", e);
- return 0L;
- } catch (IOException e) {
- LOG.error("Error getting operating system pid from the shell.", e);
- return 0L;
- } finally {
- if (p != null) {
- p.destroy();
- }
- }
- try {
- return Long.parseLong(sb.toString());
- } catch (NumberFormatException e) {
- LOG.error("Error parsing operating system pid from the shell.", e);
- return 0L;
- }
- }
-
- /**
- * Get the process ID by looking at the name of the managed bean for the
- * runtime system of the Java virtual machine.<p/>
- *
- * Although this is undocumented, in the Oracle JVM this name is of the form
- * [OS_PROCESS_ID]@[HOSTNAME].
- */
- private static long getOsPidFromManagementFactory() {
- try {
- return Long.parseLong(ManagementFactory.getRuntimeMXBean().
- getName().split("@")[0]);
- } catch (NumberFormatException e) {
- LOG.error("Failed to get the operating system process ID from the name " +
- "of the managed bean for the JVM.", e);
- return 0L;
- }
- }
-
- public String get() {
- return tracerId;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/main/java/org/apache/htrace/core/TracerPool.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/main/java/org/apache/htrace/core/TracerPool.java b/htrace-core/src/main/java/org/apache/htrace/core/TracerPool.java
deleted file mode 100644
index 26e39f5..0000000
--- a/htrace-core/src/main/java/org/apache/htrace/core/TracerPool.java
+++ /dev/null
@@ -1,285 +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.core;
-
-import java.util.Arrays;
-import java.util.HashSet;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * A pool of Tracer objects.
- *
- * There may be more than one {@link Tracer} running inside a single 'process'; for example,
- * unit tests may spin up a DataNode, a NameNode, and HDFS clients all running in a single JVM
- * instance, each with its own Tracer. TracerPool is where all Tracer instances register
- * on creation so Tracers can coordinate around shared resources such as {@link SpanReceiver}
- * instances. TracerPool takes care of properly cleaning up registered Tracer instances on shutdown.
- */
-public class TracerPool {
- private static final Log LOG = LogFactory.getLog(TracerPool.class);
-
- /**
- * The global pool of tracer objects.
- *
- * This is the pool that new tracers get put into by default.
- */
- static final TracerPool GLOBAL = new TracerPool("Global");
-
- /**
- * The shutdown hook which closes the Tracers in this pool when the process is
- * shutting down.
- */
- private class SpanReceiverShutdownHook extends Thread {
- SpanReceiverShutdownHook() {
- setName("SpanReceiverShutdownHook");
- setDaemon(false);
- }
-
- @Override
- public void run() {
- removeAndCloseAllSpanReceivers();
- }
- }
-
- /**
- * The name of this TracerPool.
- */
- private final String name;
-
- /**
- * The current span receivers which these tracers are using.
- *
- * Can be read locklessly. Must be written under the lock.
- * The array itself should never be modified.
- */
- private volatile SpanReceiver[] curReceivers;
-
- /**
- * The currently installed shutdown hook, or null if no hook has been
- * installed.
- */
- private SpanReceiverShutdownHook shutdownHook;
-
- /**
- * The current Tracers.
- */
- private final HashSet<Tracer> curTracers;
-
- /**
- * Get the global tracer pool.
- */
- public static TracerPool getGlobalTracerPool() {
- return GLOBAL;
- }
-
- public TracerPool(String name) {
- this.name = name;
- this.shutdownHook = null;
- this.curTracers = new HashSet<Tracer>();
- this.curReceivers = new SpanReceiver[0];
- }
-
- /**
- * Return the name of this TracerPool.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns an array of all the current span receivers.
- *
- * Note that if the current span receivers change, those changes will not be
- * reflected in this array. In other words, this array may be stale.
- */
- public SpanReceiver[] getReceivers() {
- return curReceivers;
- }
-
- /**
- * Add a new span receiver.
- *
- * @param receiver The new receiver to add.
- *
- * @return True if the new receiver was added; false if it
- * already was there.
- */
- public synchronized boolean addReceiver(SpanReceiver receiver) {
- SpanReceiver[] receivers = curReceivers;
- for (int i = 0; i < receivers.length; i++) {
- if (receivers[i] == receiver) {
- LOG.trace(toString() + ": can't add receiver " + receiver.toString() +
- " since it is already in this pool.");
- return false;
- }
- }
- SpanReceiver[] newReceivers =
- Arrays.copyOf(receivers, receivers.length + 1);
- newReceivers[receivers.length] = receiver;
- registerShutdownHookIfNeeded();
- curReceivers = newReceivers;
- LOG.trace(toString() + ": added receiver " + receiver.toString());
- return true;
- }
-
- /**
- * Register the shutdown hook if needed.
- */
- private synchronized void registerShutdownHookIfNeeded() {
- if (shutdownHook != null) {
- return;
- }
- shutdownHook = new SpanReceiverShutdownHook();
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- LOG.trace(toString() + ": registered shutdown hook.");
- }
-
- /**
- * Remove a span receiver.
- *
- * @param receiver The receiver to remove.
- *
- * @return True if the receiver was removed; false if it
- * did not exist in this pool.
- */
- public synchronized boolean removeReceiver(SpanReceiver receiver) {
- SpanReceiver[] receivers = curReceivers;
- for (int i = 0; i < receivers.length; i++) {
- if (receivers[i] == receiver) {
- SpanReceiver[] newReceivers = new SpanReceiver[receivers.length - 1];
- System.arraycopy(receivers, 0, newReceivers, 0, i);
- System.arraycopy(receivers, i + 1, newReceivers, i,
- receivers.length - i - 1);
- curReceivers = newReceivers;
- LOG.trace(toString() + ": removed receiver " + receiver.toString());
- return true;
- }
- }
- LOG.trace(toString() + ": can't remove receiver " + receiver.toString() +
- " since it's not currently in this pool.");
- return false;
- }
-
- /**
- * Remove and close a span receiver.
- *
- * @param receiver The receiver to remove.
- *
- * @return True if the receiver was removed; false if it
- * did not exist in this pool.
- */
- public boolean removeAndCloseReceiver(SpanReceiver receiver) {
- if (!removeReceiver(receiver)) {
- return false;
- }
- try {
- LOG.trace(toString() + ": closing receiver " + receiver.toString());
- receiver.close();
- } catch (Throwable t) {
- LOG.error(toString() + ": error closing " + receiver.toString(), t);
- }
- return true;
- }
-
- /**
- * Remove and close all of the span receivers.
- */
- private synchronized void removeAndCloseAllSpanReceivers() {
- SpanReceiver[] receivers = curReceivers;
- curReceivers = new SpanReceiver[0];
- for (SpanReceiver receiver : receivers) {
- try {
- LOG.trace(toString() + ": closing receiver " + receiver.toString());
- receiver.close();
- } catch (Throwable t) {
- LOG.error(toString() + ": error closing " + receiver.toString(), t);
- }
- }
- }
-
- /**
- * Given a SpanReceiver class name, return the existing instance of that span
- * receiver, if possible; otherwise, invoke the callable to create a new
- * instance.
- *
- * @param className The span receiver class name.
- * @param conf The HTrace configuration.
- * @param classLoader The class loader to use.
- *
- * @return The SpanReceiver.
- */
- public synchronized SpanReceiver loadReceiverType(String className,
- HTraceConfiguration conf, ClassLoader classLoader) {
- SpanReceiver[] receivers = curReceivers;
- for (SpanReceiver receiver : receivers) {
- if (receiver.getClass().getName().equals(className)) {
- LOG.trace(toString() + ": returning a reference to receiver " +
- receiver.toString());
- return receiver;
- }
- }
- LOG.trace(toString() + ": creating a new SpanReceiver of type " +
- className);
- SpanReceiver receiver = new SpanReceiver.Builder(conf).
- className(className).
- classLoader(classLoader).
- build();
- addReceiver(receiver);
- return receiver;
- }
-
- /**
- * Returns an array of all the current Tracers.
- *
- * Note that if the current Tracers change, those changes will not be
- * reflected in this array. In other words, this array may be stale.
- */
- public synchronized Tracer[] getTracers() {
- return curTracers.toArray(new Tracer[curTracers.size()]);
- }
-
- /**
- * Add a new Tracer.
- */
- synchronized void addTracer(Tracer tracer) {
- if (curTracers.add(tracer)) {
- LOG.trace(toString() + ": adding tracer " + tracer.toString());
- }
- }
-
- /**
- * Remove a Tracer.
- *
- * If the Tracer removed was the last one, we will close all the SpanReceiver
- * objects that we're managing.
- */
- synchronized void removeTracer(Tracer tracer) {
- if (curTracers.remove(tracer)) {
- LOG.trace(toString() + ": removing tracer " + tracer.toString());
- if (curTracers.size() == 0) {
- removeAndCloseAllSpanReceivers();
- }
- }
- }
-
- @Override
- public String toString() {
- return "TracerPool(" + name + ")";
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestBadClient.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestBadClient.java b/htrace-core/src/test/java/org/apache/htrace/core/TestBadClient.java
deleted file mode 100644
index 87ae8e9..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestBadClient.java
+++ /dev/null
@@ -1,205 +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.core;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.hamcrest.CoreMatchers.containsString;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestBadClient {
- @After
- public void clearBadState() {
- // Clear the bad trace state so that we don't disrupt other unit tests
- // that run in this JVM.
- Tracer.threadLocalScope.set(null);
- }
-
- /**
- * Test closing an outer scope when an inner one is still active.
- */
- @Test
- public void TestClosingOuterScope() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestClosingOuterScopeTracer").
- tracerPool(new TracerPool("TestClosingOuterScope")).
- conf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
- boolean gotException = false;
- TraceScope outerScope = tracer.newScope("outer");
- TraceScope innerScope = tracer.newScope("inner");
- try {
- outerScope.close();
- } catch (RuntimeException e) {
- assertThat(e.getMessage(),
- containsString("it is not the current TraceScope"));
- gotException = true;
- }
- assertTrue("Expected to get exception because of improper " +
- "scope closure.", gotException);
- innerScope.close();
- tracer.close();
- }
-
- /**
- * Test calling detach() two times on a scope object.
- */
- @Test
- public void TestDoubleDetachIsCaught() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestDoubleDetach").
- tracerPool(new TracerPool("TestDoubleDetachIsCaught")).
- conf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
- boolean gotException = false;
- TraceScope myScope = tracer.newScope("myScope");
- myScope.detach();
- try {
- myScope.detach();
- } catch (RuntimeException e) {
- assertThat(e.getMessage(),
- containsString("it is already detached."));
- gotException = true;
- }
- assertTrue("Expected to get exception because of double TraceScope " +
- "detach.", gotException);
- tracer.close();
- }
-
- /**
- * Test calling detach() two times on a scope object.
- */
- @Test
- public void TestDoubleDetachOnNullScope() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestDoubleDetachOnNullScope").
- tracerPool(new TracerPool("TestDoubleDetachOnNullScope")).
- conf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "NeverSampler")).build();
- boolean gotException = false;
- TraceScope myScope = tracer.newScope("myScope");
- myScope.detach();
- try {
- myScope.detach();
- } catch (RuntimeException e) {
- assertThat(e.getMessage(),
- containsString("it is already detached."));
- gotException = true;
- }
- assertTrue("Expected to get exception because of double TraceScope " +
- "detach on NullScope.", gotException);
- tracer.close();
- }
-
- /**
- * Test calling reattach() two times on a scope object.
- */
- @Test
- public void TestDoubleReattachIsCaught() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestDoubleReattach").
- tracerPool(new TracerPool("TestDoubleReattachIsCaught")).
- conf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
- boolean gotException = false;
- TraceScope myScope = tracer.newScope("myScope");
- myScope.detach();
- myScope.reattach();
- try {
- myScope.reattach();
- } catch (RuntimeException e) {
- assertThat(e.getMessage(),
- containsString("it is not detached."));
- gotException = true;
- }
- assertTrue("Expected to get exception because of double TraceScope " +
- "reattach.", gotException);
- tracer.close();
- }
-
- private static class ScopeHolder {
- TraceScope scope;
-
- void set(TraceScope scope) {
- this.scope = scope;
- }
- }
-
- /**
- * Test correctly passing spans between threads using detach().
- */
- @Test
- public void TestPassingSpanBetweenThreads() throws Exception {
- final Tracer tracer = new Tracer.Builder().
- name("TestPassingSpanBetweenThreads").
- tracerPool(new TracerPool("TestPassingSpanBetweenThreads")).
- conf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
- POJOSpanReceiver receiver =
- new POJOSpanReceiver(HTraceConfiguration.EMPTY);
- tracer.getTracerPool().addReceiver(receiver);
- final ScopeHolder scopeHolder = new ScopeHolder();
- Thread th = new Thread(new Runnable() {
- @Override
- public void run() {
- TraceScope workerScope = tracer.newScope("workerSpan");
- workerScope.detach();
- scopeHolder.set(workerScope);
- }
- });
- th.start();
- th.join();
- TraceScope workerScope = scopeHolder.scope;
- SpanId workerScopeId = workerScope.getSpan().getSpanId();
-
- // Create new scope whose parent is the worker thread's span.
- workerScope.reattach();
- TraceScope nested = tracer.newScope("nested");
- nested.close();
- // Create another span which also descends from the worker thread's span.
- TraceScope nested2 = tracer.newScope("nested2");
- nested2.close();
-
- // Close the worker thread's span.
- workerScope.close();
-
- // We can create another descendant, even though the worker thread's span
- // has been stopped.
- TraceScope lateChildScope = tracer.newScope("lateChild", workerScopeId);
- lateChildScope.close();
- tracer.close();
-
- TraceGraph traceGraph = new TraceGraph(receiver.getSpans());
- Collection<Span> rootSpans =
- traceGraph.getSpansByParent().find(SpanId.INVALID);
- Assert.assertEquals(1, rootSpans.size());
- Assert.assertEquals(workerScopeId,
- rootSpans.iterator().next().getSpanId());
- Collection<Span> childSpans =
- traceGraph.getSpansByParent().find(workerScopeId);
- Assert.assertEquals(3, childSpans.size());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestCountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestCountSampler.java b/htrace-core/src/test/java/org/apache/htrace/core/TestCountSampler.java
deleted file mode 100644
index e26115d..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestCountSampler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.htrace.core;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestCountSampler {
-
- @Test
- public void testNext() {
- CountSampler half = new CountSampler(HTraceConfiguration.
- fromKeyValuePairs("sampler.frequency", "2"));
- CountSampler hundred = new CountSampler(HTraceConfiguration.
- fromKeyValuePairs("sampler.frequency", "100"));
- int halfCount = 0;
- int hundredCount = 0;
- for (int i = 0; i < 200; i++) {
- if (half.next())
- halfCount++;
- if (hundred.next())
- hundredCount++;
- }
- Assert.assertEquals(2, hundredCount);
- Assert.assertEquals(100, halfCount);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestHTrace.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestHTrace.java b/htrace-core/src/test/java/org/apache/htrace/core/TestHTrace.java
deleted file mode 100644
index 06ca189..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestHTrace.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.core;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.htrace.core.TraceGraph.SpansByParent;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestHTrace {
- @Test
- public void TestTracerCreateAndClose() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestSimpleScope").
- tracerPool(new TracerPool("TestTracerCreateAndClose")).
- conf(HTraceConfiguration.fromKeyValuePairs(
- "sampler.classes", "AlwaysSampler")).
- build();
- POJOSpanReceiver receiver =
- new POJOSpanReceiver(HTraceConfiguration.EMPTY);
- tracer.getTracerPool().addReceiver(receiver);
- tracer.close();
- Assert.assertTrue(receiver.getSpans().isEmpty());
- }
-
- @Test
- public void TestSimpleScope() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestSimpleScope").
- tracerPool(new TracerPool("TestSimpleScope")).
- conf(HTraceConfiguration.fromKeyValuePairs(
- "sampler.classes", "AlwaysSampler")).
- build();
- POJOSpanReceiver receiver =
- new POJOSpanReceiver(HTraceConfiguration.EMPTY);
- tracer.getTracerPool().addReceiver(receiver);
- TraceScope scope = tracer.newScope("Foo");
- scope.close();
- tracer.close();
- Assert.assertEquals(1, receiver.getSpans().size());
- Span span = receiver.getSpans().iterator().next();
- Assert.assertEquals(0, span.getParents().length);
- }
-
- @Test
- public void TestCreateSpans() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("TestCreateSpans").
- tracerPool(new TracerPool("TestCreateSpans")).
- conf(HTraceConfiguration.fromKeyValuePairs(
- "sampler.classes", "AlwaysSampler")).
- build();
- POJOSpanReceiver receiver =
- new POJOSpanReceiver(HTraceConfiguration.EMPTY);
- tracer.getTracerPool().addReceiver(receiver);
- TraceCreator traceCreator = new TraceCreator(tracer);
- traceCreator.createSampleRpcTrace();
- traceCreator.createSimpleTrace();
- traceCreator.createThreadedTrace();
- tracer.close();
- TraceGraph traceGraph = new TraceGraph(receiver.getSpans());
- Collection<Span> roots = traceGraph.getSpansByParent().find(SpanId.INVALID);
- Assert.assertTrue("Trace tree must have roots", !roots.isEmpty());
- Assert.assertEquals(3, roots.size());
-
- Map<String, Span> descriptionToRootSpan = new HashMap<String, Span>();
- for (Span root : roots) {
- descriptionToRootSpan.put(root.getDescription(), root);
- }
-
- Assert.assertTrue(descriptionToRootSpan.keySet().contains(
- TraceCreator.RPC_TRACE_ROOT));
- Assert.assertTrue(descriptionToRootSpan.keySet().contains(
- TraceCreator.SIMPLE_TRACE_ROOT));
- Assert.assertTrue(descriptionToRootSpan.keySet().contains(
- TraceCreator.THREADED_TRACE_ROOT));
-
- SpansByParent spansByParentId = traceGraph.getSpansByParent();
-
- Span rpcTraceRoot = descriptionToRootSpan.get(TraceCreator.RPC_TRACE_ROOT);
- Assert.assertEquals(1, spansByParentId.find(rpcTraceRoot.getSpanId()).size());
-
- Span rpcTraceChild1 = spansByParentId.find(rpcTraceRoot.getSpanId())
- .iterator().next();
- Assert.assertEquals(1, spansByParentId.find(rpcTraceChild1.getSpanId()).size());
-
- Span rpcTraceChild2 = spansByParentId.find(rpcTraceChild1.getSpanId())
- .iterator().next();
- Assert.assertEquals(1, spansByParentId.find(rpcTraceChild2.getSpanId()).size());
-
- Span rpcTraceChild3 = spansByParentId.find(rpcTraceChild2.getSpanId())
- .iterator().next();
- Assert.assertEquals(0, spansByParentId.find(rpcTraceChild3.getSpanId()).size());
- }
-
- @Test(timeout=60000)
- public void testRootSpansHaveNonZeroSpanId() throws Exception {
- Tracer tracer = new Tracer.Builder().
- name("testRootSpansHaveNonZeroSpanId").
- tracerPool(new TracerPool("testRootSpansHaveNonZeroSpanId")).
- conf(HTraceConfiguration.fromKeyValuePairs(
- "sampler.classes", "AlwaysSampler")).build();
- TraceScope scope = tracer.
- newScope("myRootSpan", new SpanId(100L, 200L));
- Assert.assertNotNull(scope);
- Assert.assertEquals("myRootSpan", scope.getSpan().getDescription());
- Assert.assertTrue(scope.getSpan().getSpanId().isValid());
- Assert.assertEquals(100L, scope.getSpan().getSpanId().getHigh());
- Assert.assertNotEquals(0L, scope.getSpan().getSpanId().getLow());
- scope.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java b/htrace-core/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java
deleted file mode 100644
index 7ca897f..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.htrace.core;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-
-public class TestHTraceConfiguration {
- @Test
- public void testGetBoolean() throws Exception {
-
- Map<String, String> m = new HashMap<String, String>();
- m.put("testTrue", " True");
- m.put("testFalse", "falsE ");
- HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
-
- // Tests for value being there
- assertTrue(configuration.getBoolean("testTrue", false));
- assertFalse(configuration.getBoolean("testFalse", true));
-
- // Test for absent
- assertTrue(configuration.getBoolean("absent", true));
- assertFalse(configuration.getBoolean("absent", false));
- }
-
- @Test
- public void testGetInt() throws Exception {
- Map<String, String> m = new HashMap<String, String>();
- m.put("a", "100");
- m.put("b", "0");
- m.put("c", "-100");
- m.put("d", "5");
-
- HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
- assertEquals(100, configuration.getInt("a", -999));
- assertEquals(0, configuration.getInt("b", -999));
- assertEquals(-100, configuration.getInt("c", -999));
- assertEquals(5, configuration.getInt("d", -999));
- assertEquals(-999, configuration.getInt("absent", -999));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java b/htrace-core/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java
deleted file mode 100644
index 9388707..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java
+++ /dev/null
@@ -1,65 +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.core;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Test;
-
-public class TestLocalFileSpanReceiver {
- @Test
- public void testUniqueLocalTraceFileName() {
- String filename1 = LocalFileSpanReceiver.getUniqueLocalTraceFileName();
- String filename2 = LocalFileSpanReceiver.getUniqueLocalTraceFileName();
- boolean eq = filename1.equals(filename2);
- if (System.getProperty("os.name").startsWith("Linux")) {
- // ${java.io.tmpdir}/[pid]
- assertTrue(eq);
- } else {
- // ${java.io.tmpdir}/[random UUID]
- assertFalse(eq);
- }
- }
-
- @Test
- public void testWriteToLocalFile() throws IOException {
- String traceFileName = LocalFileSpanReceiver.getUniqueLocalTraceFileName();
- Tracer tracer = new Tracer.Builder().
- name("testWriteToLocalFileTracer").
- tracerPool(new TracerPool("testWriteToLocalFile")).
- conf(HTraceConfiguration.fromKeyValuePairs(
- "sampler.classes", "AlwaysSampler",
- "span.receiver.classes", LocalFileSpanReceiver.class.getName(),
- "local.file.span.receiver.path", traceFileName,
- "tracer.id", "%{tname}")).
- build();
- TraceScope scope = tracer.newScope("testWriteToLocalFile");
- scope.close();
- tracer.close();
-
- ObjectMapper mapper = new ObjectMapper();
- MilliSpan span = mapper.readValue(new File(traceFileName), MilliSpan.class);
- assertEquals("testWriteToLocalFile", span.getDescription());
- assertEquals("testWriteToLocalFileTracer", span.getTracerId());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestMilliSpan.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestMilliSpan.java b/htrace-core/src/test/java/org/apache/htrace/core/TestMilliSpan.java
deleted file mode 100644
index 7ce1fdb..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestMilliSpan.java
+++ /dev/null
@@ -1,145 +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.core;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.ThreadLocalRandom;
-
-public class TestMilliSpan {
- private void compareSpans(Span expected, Span got) throws Exception {
- assertEquals(expected.getStartTimeMillis(), got.getStartTimeMillis());
- assertEquals(expected.getStopTimeMillis(), got.getStopTimeMillis());
- assertEquals(expected.getDescription(), got.getDescription());
- assertEquals(expected.getSpanId(), got.getSpanId());
- assertEquals(expected.getTracerId(), got.getTracerId());
- assertTrue(Arrays.equals(expected.getParents(), got.getParents()));
- Map<String, String> expectedT = expected.getKVAnnotations();
- Map<String, String> gotT = got.getKVAnnotations();
- if (expectedT == null) {
- assertEquals(null, gotT);
- } else {
- assertEquals(expectedT.size(), gotT.size());
- for (String key : expectedT.keySet()) {
- assertEquals(expectedT.get(key), gotT.get(key));
- }
- }
- List<TimelineAnnotation> expectedTimeline =
- expected.getTimelineAnnotations();
- List<TimelineAnnotation> gotTimeline =
- got.getTimelineAnnotations();
- if (expectedTimeline == null) {
- assertEquals(null, gotTimeline);
- } else {
- assertEquals(expectedTimeline.size(), gotTimeline.size());
- Iterator<TimelineAnnotation> iter = gotTimeline.iterator();
- for (TimelineAnnotation expectedAnn : expectedTimeline) {
- TimelineAnnotation gotAnn = iter.next();
- assertEquals(expectedAnn.getMessage(), gotAnn.getMessage());
- assertEquals(expectedAnn.getTime(), gotAnn.getTime());
- }
- }
- }
-
- @Test
- public void testJsonSerialization() throws Exception {
- MilliSpan span = new MilliSpan.Builder().
- description("foospan").
- begin(123L).
- end(456L).
- parents(new SpanId[] { new SpanId(7L, 7L) }).
- tracerId("b2404.halxg.com:8080").
- spanId(new SpanId(7L, 8L)).
- build();
- String json = span.toJson();
- MilliSpan dspan = MilliSpan.fromJson(json);
- compareSpans(span, dspan);
- }
-
- @Test
- public void testJsonSerializationWithNegativeLongValue() throws Exception {
- MilliSpan span = new MilliSpan.Builder().
- description("foospan").
- begin(-1L).
- end(-1L).
- parents(new SpanId[] { new SpanId(-1L, -1L) }).
- tracerId("b2404.halxg.com:8080").
- spanId(new SpanId(-1L, -2L)).
- build();
- String json = span.toJson();
- MilliSpan dspan = MilliSpan.fromJson(json);
- compareSpans(span, dspan);
- }
-
- @Test
- public void testJsonSerializationWithRandomLongValue() throws Exception {
- SpanId parentId = SpanId.fromRandom();
- MilliSpan span = new MilliSpan.Builder().
- description("foospan").
- begin(ThreadLocalRandom.current().nextLong()).
- end(ThreadLocalRandom.current().nextLong()).
- parents(new SpanId[] { parentId }).
- tracerId("b2404.halxg.com:8080").
- spanId(parentId.newChildId()).
- build();
- String json = span.toJson();
- MilliSpan dspan = MilliSpan.fromJson(json);
- compareSpans(span, dspan);
- }
-
- @Test
- public void testJsonSerializationWithOptionalFields() throws Exception {
- MilliSpan.Builder builder = new MilliSpan.Builder().
- description("foospan").
- begin(300).
- end(400).
- parents(new SpanId[] { }).
- tracerId("b2408.halxg.com:8080").
- spanId(new SpanId(111111111L, 111111111L));
- Map<String, String> traceInfo = new HashMap<String, String>();
- traceInfo.put("abc", "123");
- traceInfo.put("def", "456");
- builder.traceInfo(traceInfo);
- List<TimelineAnnotation> timeline = new LinkedList<TimelineAnnotation>();
- timeline.add(new TimelineAnnotation(310L, "something happened"));
- timeline.add(new TimelineAnnotation(380L, "something else happened"));
- timeline.add(new TimelineAnnotation(390L, "more things"));
- builder.timeline(timeline);
- MilliSpan span = builder.build();
- String json = span.toJson();
- MilliSpan dspan = MilliSpan.fromJson(json);
- compareSpans(span, dspan);
- }
-
- @Test
- public void testJsonSerializationWithFieldsNotSet() throws Exception {
- MilliSpan span = new MilliSpan.Builder().build();
- String json = span.toJson();
- MilliSpan dspan = MilliSpan.fromJson(json);
- compareSpans(span, dspan);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestNullScope.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestNullScope.java b/htrace-core/src/test/java/org/apache/htrace/core/TestNullScope.java
deleted file mode 100644
index c8ed7f1..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestNullScope.java
+++ /dev/null
@@ -1,43 +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.core;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestNullScope {
- private void verifyNullScope(TraceScope scope) {
- Assert.assertTrue(null == scope.getSpan());
- Assert.assertFalse(scope.detached);
- scope.detach();
- Assert.assertTrue(scope.detached);
- scope.reattach();
- Assert.assertFalse(scope.detached);
- scope.close();
- }
-
- @Test
- public void testNullScope() {
- Tracer tracer = new Tracer.Builder().
- name("testNullScope").
- tracerPool(new TracerPool("testNullScope")).
- conf(HTraceConfiguration.EMPTY).
- build();
- verifyNullScope(tracer.newScope("testNullScope"));
- verifyNullScope(tracer.newNullScope());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestSampler.java b/htrace-core/src/test/java/org/apache/htrace/core/TestSampler.java
deleted file mode 100644
index 2305d9f..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestSampler.java
+++ /dev/null
@@ -1,100 +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.core;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestSampler {
- private Sampler[] getSamplersFromConf(HTraceConfiguration conf) {
- Tracer tracer = new Tracer.Builder().
- name("MyTracer").
- tracerPool(new TracerPool("getSamplersFromConf")).
- conf(conf).
- build();
- Sampler[] samplers = tracer.getSamplers();
- tracer.close();
- return samplers;
- }
-
- private void checkArrayContains(List<Class<? extends Sampler>> expected,
- Sampler[] samplers) {
- for (Iterator<Class<? extends Sampler>> iter = expected.iterator();
- iter.hasNext(); ) {
- Class<? extends Sampler> samplerClass = iter.next();
- boolean found = false;
- for (int i = 0; i < samplers.length; i++) {
- if (samplers[i] != null) {
- if (samplers[i].getClass().equals(samplerClass)) {
- samplers[i] = null;
- found = true;
- break;
- }
- }
- }
- Assert.assertTrue("Failed to find sampler class " +
- samplerClass.getName(), found);
- }
- for (int i = 0; i < samplers.length; i++) {
- if (samplers[i] != null) {
- Assert.fail("Got extra sampler of type " +
- samplers.getClass().getName());
- }
- }
- }
-
- private void checkArrayContains(Class<? extends Sampler> expected, Sampler[] samplers) {
- LinkedList<Class<? extends Sampler>> expectedList =
- new LinkedList<Class<? extends Sampler>>();
- expectedList.add(expected);
- checkArrayContains(expectedList, samplers);
- }
-
- @Test
- public void testTracerBuilderCreatesCorrectSamplers() {
- Sampler[] samplers = getSamplersFromConf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "AlwaysSampler"));
- checkArrayContains(AlwaysSampler.class, samplers);
-
- samplers = getSamplersFromConf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "NeverSampler"));
- checkArrayContains(NeverSampler.class, samplers);
-
- samplers = getSamplersFromConf(HTraceConfiguration.
- fromKeyValuePairs("sampler.classes", "NonExistentSampler"));
- Assert.assertEquals(0, samplers.length);
-
- samplers = getSamplersFromConf(HTraceConfiguration.EMPTY);
- Assert.assertEquals(0, samplers.length);
- }
-
- @Test
- public void testAlwaysSampler() {
- AlwaysSampler sampler = new AlwaysSampler(HTraceConfiguration.EMPTY);
- Assert.assertTrue(sampler.next());
- }
-
- @Test
- public void testNeverSampler() {
- NeverSampler sampler = new NeverSampler(HTraceConfiguration.EMPTY);
- Assert.assertTrue(!sampler.next());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestSpanId.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestSpanId.java b/htrace-core/src/test/java/org/apache/htrace/core/TestSpanId.java
deleted file mode 100644
index bb57368..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestSpanId.java
+++ /dev/null
@@ -1,72 +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.core;
-
-import java.util.Random;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestSpanId {
- private void testRoundTrip(SpanId id) throws Exception {
- String str = id.toString();
- SpanId id2 = SpanId.fromString(str);
- Assert.assertEquals(id, id2);
- }
-
- @Test
- public void testToStringAndFromString() throws Exception {
- testRoundTrip(SpanId.INVALID);
- testRoundTrip(new SpanId(0x1234567812345678L, 0x1234567812345678L));
- testRoundTrip(new SpanId(0xf234567812345678L, 0xf234567812345678L));
- testRoundTrip(new SpanId(0xffffffffffffffffL, 0xffffffffffffffffL));
- Random rand = new Random(12345);
- for (int i = 0; i < 100; i++) {
- testRoundTrip(new SpanId(rand.nextLong(), rand.nextLong()));
- }
- }
-
- @Test
- public void testValidAndInvalidIds() throws Exception {
- Assert.assertFalse(SpanId.INVALID.isValid());
- Assert.assertTrue(
- new SpanId(0x1234567812345678L, 0x1234567812345678L).isValid());
- Assert.assertTrue(
- new SpanId(0xf234567812345678L, 0xf234567812345678L).isValid());
- }
-
- private void expectLessThan(SpanId a, SpanId b) throws Exception {
- int cmp = a.compareTo(b);
- Assert.assertTrue("Expected " + a + " to be less than " + b,
- (cmp < 0));
- int cmp2 = b.compareTo(a);
- Assert.assertTrue("Expected " + b + " to be greater than " + a,
- (cmp2 > 0));
- }
-
- @Test
- public void testIdComparisons() throws Exception {
- expectLessThan(new SpanId(0x0000000000000001L, 0x0000000000000001L),
- new SpanId(0x0000000000000001L, 0x0000000000000002L));
- expectLessThan(new SpanId(0x0000000000000001L, 0x0000000000000001L),
- new SpanId(0x0000000000000002L, 0x0000000000000000L));
- expectLessThan(SpanId.INVALID,
- new SpanId(0xffffffffffffffffL, 0xffffffffffffffffL));
- expectLessThan(new SpanId(0x1234567812345678L, 0x1234567812345678L),
- new SpanId(0x1234567812345678L, 0xf234567812345678L));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java b/htrace-core/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java
deleted file mode 100644
index b97d624..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java
+++ /dev/null
@@ -1,127 +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.core;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-public class TestSpanReceiverBuilder {
- private static final Log LOG =
- LogFactory.getLog(TestSpanReceiverBuilder.class);
-
- private List<SpanReceiver> createSpanReceivers(String classes) {
- Tracer tracer = new Tracer.Builder().
- name("MyTracer").
- tracerPool(new TracerPool("createSpanReceivers")).
- conf(HTraceConfiguration.fromKeyValuePairs(
- "span.receiver.classes", classes)).
- build();
- SpanReceiver[] receivers = tracer.getTracerPool().getReceivers();
- tracer.close();
- LinkedList<SpanReceiver> receiverList = new LinkedList<SpanReceiver>();
- for (SpanReceiver item: receivers) {
- receiverList.add(item);
- }
- return receiverList;
- }
-
- @Test
- public void TestCreateStandardSpanReceivers() {
- List<SpanReceiver> receivers;
- receivers = createSpanReceivers("");
- Assert.assertTrue(receivers.isEmpty());
- receivers = createSpanReceivers("POJOSpanReceiver");
- Assert.assertTrue(receivers.get(0).getClass().getName().
- equals("org.apache.htrace.core.POJOSpanReceiver"));
- receivers = createSpanReceivers(
- "org.apache.htrace.core.StandardOutSpanReceiver");
- Assert.assertTrue(receivers.get(0).getClass().getName().
- equals("org.apache.htrace.core.StandardOutSpanReceiver"));
- receivers = createSpanReceivers(
- "POJOSpanReceiver;StandardOutSpanReceiver");
- Assert.assertEquals(2, receivers.size());
- for (Iterator<SpanReceiver> iter = receivers.iterator(); iter.hasNext();) {
- SpanReceiver receiver = iter.next();
- if (receiver.getClass().getName().equals(
- "org.apache.htrace.core.POJOSpanReceiver")) {
- iter.remove();
- break;
- }
- }
- for (Iterator<SpanReceiver> iter = receivers.iterator(); iter.hasNext();) {
- SpanReceiver receiver = iter.next();
- if (receiver.getClass().getName().equals(
- "org.apache.htrace.core.StandardOutSpanReceiver")) {
- iter.remove();
- break;
- }
- }
- Assert.assertEquals(0, receivers.size());
- }
-
- public static class GoodSpanReceiver extends SpanReceiver {
- public GoodSpanReceiver(HTraceConfiguration conf) {
- }
-
- @Override
- public void receiveSpan(Span span) {
- }
-
- @Override
- public void close() throws IOException {
- }
- }
-
- public static class BadSpanReceiver extends SpanReceiver {
- public BadSpanReceiver(HTraceConfiguration conf) {
- throw new RuntimeException("Can't create BadSpanReceiver");
- }
-
- @Override
- public void receiveSpan(Span span) {
- }
-
- @Override
- public void close() throws IOException {
- }
- }
-
- /**
- * Test trying to create a SpanReceiver that experiences an error in the
- * constructor.
- */
- @Test
- public void testGetSpanReceiverWithConstructorError() throws Exception {
- List<SpanReceiver> receivers;
- receivers = createSpanReceivers(
- GoodSpanReceiver.class.getName());
- Assert.assertEquals(1, receivers.size());
- Assert.assertTrue(receivers.get(0).getClass().getName().
- contains("GoodSpanReceiver"));
- receivers = createSpanReceivers(
- BadSpanReceiver.class.getName());
- Assert.assertEquals(0, receivers.size());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TestTracerId.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TestTracerId.java b/htrace-core/src/test/java/org/apache/htrace/core/TestTracerId.java
deleted file mode 100644
index 1e842c5..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TestTracerId.java
+++ /dev/null
@@ -1,52 +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.core;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-
-import org.junit.Test;
-
-public class TestTracerId {
- private void testTracerIdImpl(String expected, String fmt) {
- assertEquals(expected, new TracerId(
- HTraceConfiguration.fromKeyValuePairs(TracerId.TRACER_ID_KEY, fmt),
- "TracerName").get());
- }
-
- @Test
- public void testSimpleTracerIds() {
- testTracerIdImpl("abc", "abc");
- testTracerIdImpl("abc", "a\\bc");
- testTracerIdImpl("abc", "ab\\c");
- testTracerIdImpl("abc", "\\a\\b\\c");
- testTracerIdImpl("a\\bc", "a\\\\bc");
- }
-
- @Test
- public void testSubstitutionVariables() throws IOException {
- testTracerIdImpl("myTracerName", "my%{tname}");
- testTracerIdImpl(TracerId.getProcessName(), "%{pname}");
- testTracerIdImpl("my." + TracerId.getProcessName(), "my.%{pname}");
- testTracerIdImpl(TracerId.getBestIpString() + ".str", "%{ip}.str");
- testTracerIdImpl("%{pname}", "\\%{pname}");
- testTracerIdImpl("%cash%money{}", "%cash%money{}");
- testTracerIdImpl("Foo." + Long.valueOf(TracerId.getOsPid()).toString(),
- "Foo.%{pid}");
- }
-}
[3/5] incubator-htrace git commit: HTRACE-259. Rename htrace-core
module to htrace-core4 to match the artifactId (stack via cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TraceCreator.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TraceCreator.java b/htrace-core/src/test/java/org/apache/htrace/core/TraceCreator.java
deleted file mode 100644
index b843999..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TraceCreator.java
+++ /dev/null
@@ -1,141 +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.core;
-
-import java.util.Random;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * Does some stuff and traces it.
- */
-public class TraceCreator {
- public static final String RPC_TRACE_ROOT = "createSampleRpcTrace";
- public static final String THREADED_TRACE_ROOT = "createThreadedTrace";
- public static final String SIMPLE_TRACE_ROOT = "createSimpleTrace";
-
- private final Tracer tracer;
-
- public TraceCreator(Tracer tracer) {
- this.tracer = tracer;
- }
-
- public void createSampleRpcTrace() {
- TraceScope s = tracer.newScope(RPC_TRACE_ROOT);
- try {
- pretendRpcSend();
- } finally {
- s.close();
- }
- }
-
- public void createSimpleTrace() {
- TraceScope s = tracer.newScope(SIMPLE_TRACE_ROOT);
- try {
- importantWork1();
- } finally {
- s.close();
- }
- }
-
- /**
- * Creates the demo trace (will create different traces from call to call).
- */
- public void createThreadedTrace() {
- TraceScope s = tracer.newScope(THREADED_TRACE_ROOT);
- try {
- Random r = ThreadLocalRandom.current();
- int numThreads = r.nextInt(4) + 1;
- Thread[] threads = new Thread[numThreads];
-
- for (int i = 0; i < numThreads; i++) {
- threads[i] = new Thread(tracer.wrap(new MyRunnable(), null));
- }
- for (int i = 0; i < numThreads; i++) {
- threads[i].start();
- }
- for (int i = 0; i < numThreads; i++) {
- try {
- threads[i].join();
- } catch (InterruptedException e) {
- }
- }
- importantWork1();
- } finally {
- s.close();
- }
- }
-
- private void importantWork1() {
- TraceScope cur = tracer.newScope("important work 1");
- try {
- Thread.sleep((long) (2000 * Math.random()));
- importantWork2();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } finally {
- cur.close();
- }
- }
-
- private void importantWork2() {
- TraceScope cur = tracer.newScope("important work 2");
- try {
- Thread.sleep((long) (2000 * Math.random()));
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } finally {
- cur.close();
- }
- }
-
- private class MyRunnable implements Runnable {
- @Override
- public void run() {
- try {
- Thread.sleep(750);
- Random r = ThreadLocalRandom.current();
- int importantNumber = 100 / r.nextInt(3);
- System.out.println("Important number: " + importantNumber);
- } catch (InterruptedException ie) {
- Thread.currentThread().interrupt();
- } catch (ArithmeticException ae) {
- TraceScope c = tracer.newScope("dealing with arithmetic exception.");
- try {
- Thread.sleep((long) (3000 * Math.random()));
- } catch (InterruptedException ie1) {
- Thread.currentThread().interrupt();
- } finally {
- c.close();
- }
- }
- }
- }
-
- public void pretendRpcSend() {
- Span span = tracer.getCurrentSpan();
- pretendRpcReceiveWithTraceInfo(span.getSpanId());
- }
-
- public void pretendRpcReceiveWithTraceInfo(SpanId parentId) {
- TraceScope s = tracer.newScope("received RPC", parentId);
- try {
- importantWork1();
- } finally {
- s.close();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/core/TraceGraph.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/core/TraceGraph.java b/htrace-core/src/test/java/org/apache/htrace/core/TraceGraph.java
deleted file mode 100644
index a06e620..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/core/TraceGraph.java
+++ /dev/null
@@ -1,176 +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.core;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TreeSet;
-
-/**
- * Used to create the graph formed by spans.
- */
-public class TraceGraph {
- private static final Log LOG = LogFactory.getLog(Tracer.class);
-
-
- public static class SpansByParent {
- /**
- * Compare two spans by span ID.
- */
- private static Comparator<Span> COMPARATOR =
- new Comparator<Span>() {
- @Override
- public int compare(Span a, Span b) {
- return a.getSpanId().compareTo(b.getSpanId());
- }
- };
-
- private final TreeSet<Span> treeSet;
-
- private final HashMap<SpanId, LinkedList<Span>> parentToSpans;
-
- SpansByParent(Collection<Span> spans) {
- TreeSet<Span> treeSet = new TreeSet<Span>(COMPARATOR);
- parentToSpans = new HashMap<SpanId, LinkedList<Span>>();
- for (Span span : spans) {
- treeSet.add(span);
- for (SpanId parent : span.getParents()) {
- LinkedList<Span> list = parentToSpans.get(parent);
- if (list == null) {
- list = new LinkedList<Span>();
- parentToSpans.put(parent, list);
- }
- list.add(span);
- }
- if (span.getParents().length == 0) {
- LinkedList<Span> list = parentToSpans.get(SpanId.INVALID);
- if (list == null) {
- list = new LinkedList<Span>();
- parentToSpans.put(SpanId.INVALID, list);
- }
- list.add(span);
- }
- }
- this.treeSet = treeSet;
- }
-
- public List<Span> find(SpanId parentId) {
- LinkedList<Span> spans = parentToSpans.get(parentId);
- if (spans == null) {
- return new LinkedList<Span>();
- }
- return spans;
- }
-
- public Iterator<Span> iterator() {
- return Collections.unmodifiableSortedSet(treeSet).iterator();
- }
- }
-
- public static class SpansByTracerId {
- /**
- * Compare two spans by process ID, and then by span ID.
- */
- private static Comparator<Span> COMPARATOR =
- new Comparator<Span>() {
- @Override
- public int compare(Span a, Span b) {
- int cmp = a.getTracerId().compareTo(b.getTracerId());
- if (cmp != 0) {
- return cmp;
- }
- return a.getSpanId().compareTo(b.getSpanId());
- }
- };
-
- private final TreeSet<Span> treeSet;
-
- SpansByTracerId(Collection<Span> spans) {
- TreeSet<Span> treeSet = new TreeSet<Span>(COMPARATOR);
- for (Span span : spans) {
- treeSet.add(span);
- }
- this.treeSet = treeSet;
- }
-
- public List<Span> find(String tracerId) {
- List<Span> spans = new ArrayList<Span>();
- Span span = new MilliSpan.Builder().
- spanId(SpanId.INVALID).
- tracerId(tracerId).
- build();
- while (true) {
- span = treeSet.higher(span);
- if (span == null) {
- break;
- }
- if (span.getTracerId().equals(tracerId)) {
- break;
- }
- spans.add(span);
- }
- return spans;
- }
-
- public Iterator<Span> iterator() {
- return Collections.unmodifiableSortedSet(treeSet).iterator();
- }
- }
-
- private final SpansByParent spansByParent;
- private final SpansByTracerId spansByTracerId;
-
- /**
- * Create a new TraceGraph
- *
- * @param spans The collection of spans to use to create this TraceGraph. Should
- * have at least one root span.
- */
- public TraceGraph(Collection<Span> spans) {
- this.spansByParent = new SpansByParent(spans);
- this.spansByTracerId = new SpansByTracerId(spans);
- }
-
- public SpansByParent getSpansByParent() {
- return spansByParent;
- }
-
- public SpansByTracerId getSpansByTracerId() {
- return spansByTracerId;
- }
-
- @Override
- public String toString() {
- StringBuilder bld = new StringBuilder();
- String prefix = "";
- for (Iterator<Span> iter = spansByParent.iterator(); iter.hasNext();) {
- Span span = iter.next();
- bld.append(prefix).append(span.toString());
- prefix = "\n";
- }
- return bld.toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core/src/test/java/org/apache/htrace/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/htrace-core/src/test/java/org/apache/htrace/util/TestUtil.java b/htrace-core/src/test/java/org/apache/htrace/util/TestUtil.java
deleted file mode 100644
index 7cb4aed..0000000
--- a/htrace-core/src/test/java/org/apache/htrace/util/TestUtil.java
+++ /dev/null
@@ -1,91 +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.util;
-
-import java.io.File;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Utilities for writing unit tests.
- */
-public class TestUtil {
- /**
- * Get a dump of the stack traces of all threads.
- */
- public static String threadDump() {
- StringBuilder dump = new StringBuilder();
- Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
- for (Map.Entry<Thread, StackTraceElement[]> e : stackTraces.entrySet()) {
- Thread thread = e.getKey();
- dump.append(String.format(
- "\"%s\" %s prio=%d tid=%d %s\njava.lang.Thread.State: %s",
- thread.getName(),
- (thread.isDaemon() ? "daemon" : ""),
- thread.getPriority(),
- thread.getId(),
- Thread.State.WAITING.equals(thread.getState()) ?
- "in Object.wait()" : thread.getState().name().toLowerCase(),
- Thread.State.WAITING.equals(thread.getState()) ?
- "WAITING (on object monitor)" : thread.getState()));
- for (StackTraceElement stackTraceElement : e.getValue()) {
- dump.append("\n at ");
- dump.append(stackTraceElement);
- }
- dump.append("\n");
- }
- return dump.toString();
- }
-
- /**
- * A callback which returns a value of type T.
- *
- * TODO: remove this when we're on Java 8, in favor of
- * java.util.function.Supplier.
- */
- public interface Supplier<T> {
- T get();
- }
-
- /**
- * Wait for a condition to become true for a configurable amount of time.
- *
- * @param check The condition to wait for.
- * @param periodMs How often to check the condition, in milliseconds.
- * @param timeoutMs How long to wait in total, in milliseconds.
- */
- public static void waitFor(Supplier<Boolean> check,
- long periodMs, long timeoutMs)
- throws TimeoutException, InterruptedException
- {
- long endNs = System.nanoTime() +
- TimeUnit.NANOSECONDS.convert(timeoutMs, TimeUnit.MILLISECONDS);
- while (true) {
- boolean result = check.get();
- if (result) {
- return;
- }
- long nowNs = System.nanoTime();
- if (nowNs >= endNs) {
- throw new TimeoutException("Timed out waiting for test condition. " +
- "Thread dump:\n" + threadDump());
- }
- Thread.sleep(periodMs);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/pom.xml
----------------------------------------------------------------------
diff --git a/htrace-core4/pom.xml b/htrace-core4/pom.xml
new file mode 100644
index 0000000..b5d3c74
--- /dev/null
+++ b/htrace-core4/pom.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>htrace-core4</artifactId>
+ <packaging>jar</packaging>
+
+ <parent>
+ <artifactId>htrace</artifactId>
+ <groupId>org.apache.htrace</groupId>
+ <version>4.1.0-incubating-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <name>htrace-core4</name>
+ <url>http://incubator.apache.org/projects/htrace.html</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <configuration>
+ <relocations>
+ <relocation>
+ <pattern>org.apache.commons.logging</pattern>
+ <shadedPattern>org.apache.htrace.commons.logging</shadedPattern>
+ </relocation>
+ <relocation>
+ <pattern>com.fasterxml.jackson</pattern>
+ <shadedPattern>org.apache.htrace.fasterxml.jackson</shadedPattern>
+ </relocation>
+ </relocations>
+ </configuration>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <!-- explicitly define maven-deploy-plugin after other to force exec order -->
+ <artifactId>maven-deploy-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <!-- Global deps. -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <!-- core specific deps. -->
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>dist</id>
+ <build>
+ <plugins>
+ <plugin>
+ <!--Make it so assembly:single does nothing in here-->
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <skipAssembly>true</skipAssembly>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/AlwaysSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/AlwaysSampler.java b/htrace-core4/src/main/java/org/apache/htrace/core/AlwaysSampler.java
new file mode 100644
index 0000000..8d5a296
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/AlwaysSampler.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+/**
+ * A Sampler that always returns true.
+ */
+public final class AlwaysSampler extends 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/CountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/CountSampler.java b/htrace-core4/src/main/java/org/apache/htrace/core/CountSampler.java
new file mode 100644
index 0000000..5a838c7
--- /dev/null
+++ b/htrace-core4/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 extends 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/HTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/HTraceConfiguration.java b/htrace-core4/src/main/java/org/apache/htrace/core/HTraceConfiguration.java
new file mode 100644
index 0000000..c6e445b
--- /dev/null
+++ b/htrace-core4/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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java b/htrace-core4/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
new file mode 100644
index 0000000..69a43b1
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/LocalFileSpanReceiver.java
@@ -0,0 +1,257 @@
+/*
+ * 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 extends 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();
+
+ 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.");
+ }
+ String pathStr = conf.get(PATH_KEY);
+ if (pathStr == null || pathStr.isEmpty()) {
+ path = getUniqueLocalTraceFileName();
+ } else {
+ path = pathStr;
+ }
+ 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);
+ }
+ }
+
+ /**
+ * 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) {
+ // 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/MilliSpan.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/MilliSpan.java b/htrace-core4/src/main/java/org/apache/htrace/core/MilliSpan.java
new file mode 100644
index 0000000..5dd6bdb
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/MilliSpan.java
@@ -0,0 +1,347 @@
+/*
+ * 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();
+ }
+ }
+
+ 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();
+ }
+ }
+
+ public static MilliSpan fromJson(String json) throws IOException {
+ return JSON_READER.readValue(json);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/NeverSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/NeverSampler.java b/htrace-core4/src/main/java/org/apache/htrace/core/NeverSampler.java
new file mode 100644
index 0000000..60cc7d2
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/NeverSampler.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+/**
+ * A Sampler that never returns true.
+ */
+public final class NeverSampler extends 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/NullScope.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/NullScope.java b/htrace-core4/src/main/java/org/apache/htrace/core/NullScope.java
new file mode 100644
index 0000000..fe76e46
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/NullScope.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+/**
+ * An empty {@link TraceScope}.
+ */
+class NullScope extends TraceScope {
+ NullScope(Tracer tracer) {
+ super(tracer, null, null);
+ }
+
+ @Override
+ public SpanId getSpanId() {
+ return SpanId.INVALID;
+ }
+
+ @Override
+ public void detach() {
+ if (detached) {
+ Tracer.throwClientError("Can't detach this TraceScope because " +
+ "it is already detached.");
+ }
+ detached = true;
+ }
+
+ @Override
+ public void reattach() {
+ if (!detached) {
+ Tracer.throwClientError("Can't reattach this TraceScope because " +
+ "it is not detached.");
+ }
+ detached = false;
+ }
+
+ @Override
+ public void close() {
+ tracer.popNullScope();
+ }
+
+ @Override
+ public String toString() {
+ return "NullScope";
+ }
+
+ @Override
+ public void addKVAnnotation(String key, String value) {
+ // do nothing
+ }
+
+ @Override
+ public void addTimelineAnnotation(String msg) {
+ // do nothing
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java b/htrace-core4/src/main/java/org/apache/htrace/core/POJOSpanReceiver.java
new file mode 100644
index 0000000..34322fa
--- /dev/null
+++ b/htrace-core4/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 extends 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/ProbabilitySampler.java b/htrace-core4/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
new file mode 100644
index 0000000..c0bb16c
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/ProbabilitySampler.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * 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 extends 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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/Sampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/Sampler.java b/htrace-core4/src/main/java/org/apache/htrace/core/Sampler.java
new file mode 100644
index 0000000..af0165c
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/Sampler.java
@@ -0,0 +1,131 @@
+/*
+ * 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.lang.reflect.Constructor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * 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() > 0.5;
+ * }
+ * </code>
+ * </pre>
+ * This would trace 50% of all gets, 75% of all puts and would not trace any other requests.
+ */
+public abstract class Sampler {
+ /**
+ * A {@link Sampler} builder. It takes a {@link Sampler} class name and
+ * constructs an instance of that class, with the provided configuration.
+ */
+ public static class Builder {
+ private static final Log LOG = LogFactory.getLog(Builder.class);
+
+ private final static String DEFAULT_PACKAGE = "org.apache.htrace.core";
+ private final HTraceConfiguration conf;
+ private String className;
+ private ClassLoader classLoader = Builder.class.getClassLoader();
+
+ public Builder(HTraceConfiguration conf) {
+ this.conf = conf;
+ reset();
+ }
+
+ public Builder reset() {
+ this.className = null;
+ return this;
+ }
+
+ public Builder className(String className) {
+ this.className = className;
+ return this;
+ }
+
+ public Builder classLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ return this;
+ }
+
+ private void throwError(String errorStr) {
+ LOG.error(errorStr);
+ throw new RuntimeException(errorStr);
+ }
+
+ private void throwError(String errorStr, Throwable e) {
+ LOG.error(errorStr, e);
+ throw new RuntimeException(errorStr, e);
+ }
+
+ 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() {
+ if (className == null || className.isEmpty()) {
+ throwError("No sampler class specified.");
+ }
+ String str = className;
+ if (!str.contains(".")) {
+ str = DEFAULT_PACKAGE + "." + str;
+ }
+ Class cls = null;
+ try {
+ cls = classLoader.loadClass(str);
+ } catch (ClassNotFoundException e) {
+ throwError("Cannot find Sampler class " + str);
+ }
+ Constructor<Sampler> ctor = null;
+ try {
+ ctor = cls.getConstructor(HTraceConfiguration.class);
+ } catch (NoSuchMethodException e) {
+ throwError("Cannot find a constructor for class " +
+ str + "which takes an HTraceConfiguration.");
+ }
+ Sampler sampler = null;
+ try {
+ LOG.debug("Creating new instance of " + str + "...");
+ sampler = ctor.newInstance(conf);
+ } catch (ReflectiveOperationException e) {
+ throwError("Reflection error when constructing " +
+ str + ".", e);
+ } catch (Throwable t) {
+ throwError("NewInstance error when constructing " +
+ str + ".", t);
+ }
+ return sampler;
+ }
+ }
+
+ public static final Sampler ALWAYS = AlwaysSampler.INSTANCE;
+ public static final Sampler NEVER = NeverSampler.INSTANCE;
+
+ public abstract boolean next();
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/Span.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/Span.java b/htrace-core4/src/main/java/org/apache/htrace/core/Span.java
new file mode 100644
index 0000000..e63d414
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/Span.java
@@ -0,0 +1,193 @@
+/*
+ * 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.List;
+import java.util.Map;
+
+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;
+
+/**
+ * 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
+ * @deprecated Since 4.0.0. Use {@link MilliSpan.Builder}
+ */
+ @Deprecated
+ 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/SpanId.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/SpanId.java b/htrace-core4/src/main/java/org/apache/htrace/core/SpanId.java
new file mode 100644
index 0000000..ed31ad3
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/SpanId.java
@@ -0,0 +1,146 @@
+/*
+ * 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;
+
+/**
+ * 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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/SpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/SpanReceiver.java b/htrace-core4/src/main/java/org/apache/htrace/core/SpanReceiver.java
new file mode 100644
index 0000000..a955ddf
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/SpanReceiver.java
@@ -0,0 +1,164 @@
+/*
+ * 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.Closeable;
+import java.lang.reflect.Constructor;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * 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>
+ */
+public abstract class SpanReceiver implements Closeable {
+ /**
+ * A {@link SpanReceiver} builder. It takes a {@link SpanReceiver} class name
+ * and constructs an instance of that class, with the provided configuration.
+ */
+ public static class Builder {
+ private static final Log LOG = LogFactory.getLog(Builder.class);
+
+ private final static String DEFAULT_PACKAGE = "org.apache.htrace.core";
+ private final HTraceConfiguration conf;
+ private boolean logErrors;
+ private String className;
+ private ClassLoader classLoader = Builder.class.getClassLoader();
+
+ public Builder(HTraceConfiguration conf) {
+ this.conf = conf;
+ reset();
+ }
+
+ /**
+ * Set this builder back to defaults.
+ *
+ * @return this instance.
+ */
+ public Builder reset() {
+ this.logErrors = true;
+ this.className = null;
+ return this;
+ }
+
+ public Builder className(final String className) {
+ this.className = className;
+ return this;
+ }
+
+ /**
+ * Configure whether we should log errors during build().
+ * @return This instance
+ */
+ public Builder logErrors(boolean logErrors) {
+ this.logErrors = logErrors;
+ return this;
+ }
+
+ public Builder classLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ return this;
+ }
+
+ private void throwError(String errorStr) {
+ if (logErrors) {
+ LOG.error(errorStr);
+ }
+ throw new RuntimeException(errorStr);
+ }
+
+ private void throwError(String errorStr, Throwable e) {
+ if (logErrors) {
+ LOG.error(errorStr, e);
+ }
+ throw new RuntimeException(errorStr, e);
+ }
+
+ public SpanReceiver build() {
+ SpanReceiver spanReceiver = newSpanReceiver();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Created new span receiver of type " +
+ spanReceiver.getClass().getName());
+ }
+ return spanReceiver;
+ }
+
+ private SpanReceiver newSpanReceiver() {
+ if ((className == null) || className.isEmpty()) {
+ throwError("No span receiver class specified.");
+ }
+ String str = className;
+ if (!str.contains(".")) {
+ str = DEFAULT_PACKAGE + "." + str;
+ }
+ Class cls = null;
+ try {
+ cls = classLoader.loadClass(str);
+ } catch (ClassNotFoundException e) {
+ throwError("Cannot find SpanReceiver class " + str);
+ }
+ Constructor<SpanReceiver> ctor = null;
+ try {
+ ctor = cls.getConstructor(HTraceConfiguration.class);
+ } catch (NoSuchMethodException e) {
+ throwError("Cannot find a constructor for class " +
+ str + "which takes an HTraceConfiguration.");
+ }
+ SpanReceiver receiver = null;
+ try {
+ LOG.debug("Creating new instance of " + str + "...");
+ receiver = ctor.newInstance(conf);
+ } catch (ReflectiveOperationException e) {
+ throwError("Reflection error when constructing " +
+ str + ".", e);
+ } catch (Throwable t) {
+ throwError("NewInstance error when constructing " +
+ str + ".", t);
+ }
+ return receiver;
+ }
+ }
+
+ /**
+ * An ID which uniquely identifies this SpanReceiver.
+ */
+ private final long id;
+
+ private static final AtomicLong HIGHEST_SPAN_RECEIVER_ID = new AtomicLong(0);
+
+ /**
+ * Get an ID uniquely identifying this SpanReceiver.
+ */
+ public final long getId() {
+ return id;
+ }
+
+ protected SpanReceiver() {
+ this.id = HIGHEST_SPAN_RECEIVER_ID.incrementAndGet();
+ }
+
+ /**
+ * Called when a Span is stopped and can now be stored.
+ */
+ public abstract void receiveSpan(Span span);
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java b/htrace-core4/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java
new file mode 100644
index 0000000..f443ec6
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/StandardOutSpanReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+
+/**
+ * Used for testing. Simply prints to standard out any spans it receives.
+ */
+public class StandardOutSpanReceiver extends SpanReceiver {
+ private static final Log LOG = LogFactory.getLog(StandardOutSpanReceiver.class);
+
+ public StandardOutSpanReceiver(HTraceConfiguration conf) {
+ LOG.trace("Created new StandardOutSpanReceiver.");
+ }
+
+ @Override
+ public void receiveSpan(Span span) {
+ System.out.println(span);
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TimelineAnnotation.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TimelineAnnotation.java b/htrace-core4/src/main/java/org/apache/htrace/core/TimelineAnnotation.java
new file mode 100644
index 0000000..18de061
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TimelineAnnotation.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+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/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TraceCallable.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TraceCallable.java b/htrace-core4/src/main/java/org/apache/htrace/core/TraceCallable.java
new file mode 100644
index 0000000..a0fec17
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TraceCallable.java
@@ -0,0 +1,56 @@
+/*
+ * 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.Callable;
+
+/**
+ * Wrap a Callable with a Span that survives a change in threads.
+ */
+public class TraceCallable<V> implements Callable<V> {
+ private final Tracer tracer;
+ private final Callable<V> impl;
+ private final TraceScope parent;
+ private final String description;
+
+ TraceCallable(Tracer tracer, TraceScope parent, Callable<V> impl,
+ String description) {
+ this.tracer = tracer;
+ this.impl = impl;
+ this.parent = parent;
+ if (description == null) {
+ this.description = Thread.currentThread().getName();
+ } else {
+ this.description = description;
+ }
+ }
+
+ @Override
+ public V call() throws Exception {
+ TraceScope chunk = tracer.newScope(description,
+ parent.getSpan().getSpanId());
+ try {
+ return impl.call();
+ } finally {
+ chunk.close();
+ }
+ }
+
+ public Callable<V> getImpl() {
+ return impl;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TraceExecutorService.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TraceExecutorService.java b/htrace-core4/src/main/java/org/apache/htrace/core/TraceExecutorService.java
new file mode 100644
index 0000000..81e31ea
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TraceExecutorService.java
@@ -0,0 +1,121 @@
+/*
+ * 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.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 Tracer tracer;
+ private final String scopeName;
+ private final ExecutorService impl;
+
+ TraceExecutorService(Tracer tracer, String scopeName,
+ ExecutorService impl) {
+ this.tracer = tracer;
+ this.scopeName = scopeName;
+ this.impl = impl;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ impl.execute(tracer.wrap(command, scopeName));
+ }
+
+ @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(tracer.wrap(task, scopeName));
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return impl.submit(tracer.wrap(task, scopeName), result);
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return impl.submit(tracer.wrap(task, scopeName));
+ }
+
+ 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(tracer.wrap(task, scopeName));
+ }
+ return result;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return impl.invokeAll(wrapCollection(tasks));
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit) throws InterruptedException {
+ return impl.invokeAll(wrapCollection(tasks), timeout, unit);
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return impl.invokeAny(wrapCollection(tasks));
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout,
+ TimeUnit unit) throws InterruptedException, ExecutionException,
+ TimeoutException {
+ return impl.invokeAny(wrapCollection(tasks), timeout, unit);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TraceRunnable.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TraceRunnable.java b/htrace-core4/src/main/java/org/apache/htrace/core/TraceRunnable.java
new file mode 100644
index 0000000..8f98708
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TraceRunnable.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+/**
+ * Wrap a Runnable with a Span that survives a change in threads.
+ */
+public class TraceRunnable implements Runnable {
+ private final Tracer tracer;
+ private final TraceScope parent;
+ private final Runnable runnable;
+ private final String description;
+
+ public TraceRunnable(Tracer tracer, TraceScope parent,
+ Runnable runnable, String description) {
+ this.tracer = tracer;
+ this.parent = parent;
+ this.runnable = runnable;
+ if (description == null) {
+ this.description = Thread.currentThread().getName();
+ } else {
+ this.description = description;
+ }
+ }
+
+ @Override
+ public void run() {
+ TraceScope chunk = tracer.newScope(description,
+ parent.getSpan().getSpanId());
+ try {
+ runnable.run();
+ } finally {
+ chunk.close();
+ }
+ }
+
+ public Runnable getRunnable() {
+ return runnable;
+ }
+}
[2/5] incubator-htrace git commit: HTRACE-259. Rename htrace-core
module to htrace-core4 to match the artifactId (stack via cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TraceScope.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TraceScope.java b/htrace-core4/src/main/java/org/apache/htrace/core/TraceScope.java
new file mode 100644
index 0000000..05a053e
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TraceScope.java
@@ -0,0 +1,128 @@
+/*
+ * 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.Closeable;
+
+/**
+ * Create a new TraceScope at major transitions. Hosts current tracing context.
+ */
+public class TraceScope implements Closeable {
+ /**
+ * The tracer to use for this scope.
+ */
+ final Tracer tracer;
+
+ /**
+ * The trace span for this scope, or null if the scope is closed.
+ *
+ * If the scope is closed, it must also be detached.
+ */
+ private final Span span;
+
+ /**
+ * The parent of this trace scope, or null if there is no parent.
+ */
+ private TraceScope parent;
+
+ /**
+ * True if this scope is detached.
+ */
+ boolean detached;
+
+ TraceScope(Tracer tracer, Span span, TraceScope parent) {
+ this.tracer = tracer;
+ this.span = span;
+ this.parent = parent;
+ this.detached = false;
+ }
+
+ /**
+ * Returns the span which this scope is managing.
+ */
+ public Span getSpan() {
+ return span;
+ }
+
+ /**
+ * Returns the span ID which this scope is managing.
+ */
+ public SpanId getSpanId() {
+ return span.getSpanId();
+ }
+
+ TraceScope getParent() {
+ return parent;
+ }
+
+ void setParent(TraceScope parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Detach this TraceScope from the current thread.
+ *
+ * It is OK to "leak" TraceScopes which have been detached. They will not
+ * consume any resources other than a small amount of memory until they are
+ * garbage collected. On the other hand, trace scopes which are still
+ * attached must never be leaked.
+ */
+ public void detach() {
+ if (detached) {
+ Tracer.throwClientError("Can't detach this TraceScope because " +
+ "it is already detached.");
+ }
+ tracer.detachScope(this);
+ detached = true;
+ parent = null;
+ }
+
+ /**
+ * Attach this TraceScope to the current thread.
+ */
+ public void reattach() {
+ if (!detached) {
+ Tracer.throwClientError("Can't reattach this TraceScope because " +
+ "it is not detached.");
+ }
+ tracer.reattachScope(this);
+ detached = false;
+ }
+
+ /**
+ * Close this TraceScope, ending the trace span it is managing.
+ */
+ @Override
+ public void close() {
+ tracer.closeScope(this);
+ }
+
+ public void addKVAnnotation(String key, String value) {
+ span.addKVAnnotation(key, value);
+ }
+
+ public void addTimelineAnnotation(String msg) {
+ span.addTimelineAnnotation(msg);
+ }
+
+ @Override
+ public String toString() {
+ return "TraceScope(tracerId=" + tracer.getTracerId() +
+ ", span=" + span.toJson() +
+ ", detached=" + detached + ")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/Tracer.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/Tracer.java b/htrace-core4/src/main/java/org/apache/htrace/core/Tracer.java
new file mode 100644
index 0000000..39d972d
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/Tracer.java
@@ -0,0 +1,673 @@
+/*
+ * 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.Closeable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Use a Tracer instance inside a 'process' to collect and distribute its trace Spans.
+ * Example processes are an HDFS DataNode or an HBase RegionServer. A Tracer instance is your
+ * one-stop shop for all things tracing.
+ *
+ * <p>
+ */
+public class Tracer implements Closeable {
+ private static final Log LOG = LogFactory.getLog(Tracer.class);
+
+ public final static String SPAN_RECEIVER_CLASSES_KEY = "span.receiver.classes";
+ public final static String SAMPLER_CLASSES_KEY = "sampler.classes";
+
+ public static class Builder {
+ private String name;
+ private HTraceConfiguration conf = HTraceConfiguration.EMPTY;
+ private ClassLoader classLoader =
+ Builder.class.getClassLoader();
+ private TracerPool tracerPool = TracerPool.GLOBAL;
+
+ /**
+ * @deprecated Since 4.0.0. Use Constructor that takes a <code>name</code> argument instead
+ */
+ @Deprecated
+ public Builder() {
+ }
+
+ public Builder(final String name) {
+ name(name);
+ }
+
+ /**
+ * @param name
+ * @return This
+ * @deprecated Since 4.0.0. Use Constructor that takes a <code>name</code> argument instead.
+ */
+ @Deprecated
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder conf(HTraceConfiguration conf) {
+ this.conf = conf;
+ return this;
+ }
+
+ public Builder tracerPool(TracerPool tracerPool) {
+ this.tracerPool = tracerPool;
+ return this;
+ }
+
+ private void loadSamplers(List<Sampler> samplers) {
+ String classNamesStr = conf.get(SAMPLER_CLASSES_KEY, "");
+ List<String> classNames = getClassNamesFromConf(classNamesStr);
+ StringBuilder bld = new StringBuilder();
+ String prefix = "";
+ for (String className : classNames) {
+ try {
+ Sampler sampler = new Sampler.Builder(conf).
+ className(className).
+ classLoader(classLoader).
+ build();
+ samplers.add(sampler);
+ bld.append(prefix).append(className);
+ prefix = ", ";
+ } catch (Throwable e) {
+ LOG.error("Failed to create SpanReceiver of type " + className, e);
+ }
+ }
+ String resultString = bld.toString();
+ if (resultString.isEmpty()) {
+ resultString = "no samplers";
+ }
+ LOG.debug(SAMPLER_CLASSES_KEY + " = " + classNamesStr +
+ "; loaded " + resultString);
+ }
+
+ private void loadSpanReceivers() {
+ String classNamesStr = conf.get(SPAN_RECEIVER_CLASSES_KEY, "");
+ List<String> classNames = getClassNamesFromConf(classNamesStr);
+ StringBuilder bld = new StringBuilder();
+ String prefix = "";
+ for (String className : classNames) {
+ try {
+ tracerPool.loadReceiverType(className, conf, classLoader);
+ bld.append(prefix).append(className);
+ prefix = ", ";
+ } catch (Throwable e) {
+ LOG.error("Failed to create SpanReceiver of type " + className, e);
+ }
+ }
+ String resultString = bld.toString();
+ if (resultString.isEmpty()) {
+ resultString = "no span receivers";
+ }
+ LOG.debug(SPAN_RECEIVER_CLASSES_KEY + " = " + classNamesStr +
+ "; loaded " + resultString);
+ }
+
+ /**
+ * Get a list of class names from the HTrace configuration.
+ * Entries which are empty will be removed. Entries which lack a package will
+ * be given the default package.
+ *
+ * @param classNamesStr A semicolon-separated string containing a list
+ * of class names.
+ * @return A list of class names.
+ */
+ private List<String> getClassNamesFromConf(String classNamesStr) {
+ String classNames[] = classNamesStr.split(";");
+ LinkedList<String> cleanedClassNames = new LinkedList<String>();
+ for (String className : classNames) {
+ String cleanedClassName = className.trim();
+ if (!cleanedClassName.isEmpty()) {
+ cleanedClassNames.add(cleanedClassName);
+ }
+ }
+ return cleanedClassNames;
+ }
+
+ public Tracer build() {
+ if (name == null) {
+ throw new RuntimeException("You must specify a name for this Tracer.");
+ }
+ LinkedList<Sampler> samplers = new LinkedList<Sampler>();
+ loadSamplers(samplers);
+ String tracerId = new TracerId(conf, name).get();
+ Tracer tracer = new Tracer(tracerId, tracerPool,
+ samplers.toArray(new Sampler[samplers.size()]));
+ tracerPool.addTracer(tracer);
+ loadSpanReceivers();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Created " + tracer + " for " + name);
+ }
+ return tracer;
+ }
+ }
+
+ /**
+ * The thread-specific context for this Tracer.
+ *
+ * This tracks the current number of trace scopes in a particular thread
+ * created by this tracer. We use this to apply our samplers only for the
+ * "top-level" spans.
+ *
+ * Note that we can't put the TraceScope objects themselves in this context,
+ * since we need to be able to use TraceScopes created by other Tracers, and
+ * this context is per-Tracer.
+ */
+ private static class ThreadContext {
+ private long depth;
+
+ ThreadContext() {
+ this.depth = 0;
+ }
+
+ boolean isTopLevel() {
+ return (depth == 0);
+ }
+
+ void pushScope() {
+ depth++;
+ }
+
+ TraceScope pushNewScope(Tracer tracer, Span span, TraceScope parentScope) {
+ TraceScope scope = new TraceScope(tracer, span, parentScope);
+ threadLocalScope.set(scope);
+ depth++;
+ return scope;
+ }
+
+ void popScope() {
+ if (depth <= 0) {
+ throwClientError("There were more trace scopes closed than " +
+ "were opened.");
+ }
+ depth--;
+ }
+ };
+
+ /**
+ * A subclass of ThreadLocal that starts off with a non-null initial value in
+ * each thread.
+ */
+ private static class ThreadLocalContext extends ThreadLocal<ThreadContext> {
+ @Override
+ protected ThreadContext initialValue() {
+ return new ThreadContext();
+ }
+ };
+
+ /**
+ * The current trace scope. This is global, so it is shared amongst all
+ * libraries using HTrace.
+ */
+ final static ThreadLocal<TraceScope> threadLocalScope =
+ new ThreadLocal<TraceScope>();
+
+ /**
+ * An empty array of SpanId objects. Can be used rather than constructing a
+ * new object whenever we need an empty array.
+ */
+ private static final SpanId EMPTY_PARENT_ARRAY[] = new SpanId[0];
+
+ /**
+ * The tracerId.
+ */
+ private final String tracerId;
+
+ /**
+ * The TracerPool which this Tracer belongs to.
+ *
+ * This gets set to null after the Tracer is closed in order to catch some
+ * use-after-close errors. Note that we do not synchronize access on this
+ * field, since it only changes when the Tracer is closed, and the Tracer
+ * should not be used after that.
+ */
+ private TracerPool tracerPool;
+
+ /**
+ * The current thread-local context for this particualr Tracer.
+ */
+ private final ThreadLocalContext threadContext;
+
+ /**
+ * The NullScope instance for this Tracer.
+ */
+ private final NullScope nullScope;
+
+ /**
+ * The currently active Samplers.
+ *
+ * Arrays are immutable once set. You must take the Tracer lock in order to
+ * set this to a new array. If this is null, the Tracer is closed.
+ */
+ private volatile Sampler[] curSamplers;
+
+ /**
+ * Log a client error, and throw an exception.
+ *
+ * @param str The message to use in the log and the exception.
+ */
+ static void throwClientError(String str) {
+ LOG.error(str);
+ throw new RuntimeException(str);
+ }
+
+ /**
+ * @return If the current thread is tracing, this function returns the Tracer that is
+ * being used; otherwise, it returns null.
+ */
+ public static Tracer curThreadTracer() {
+ TraceScope traceScope = threadLocalScope.get();
+ if (traceScope == null) {
+ return null;
+ }
+ return traceScope.tracer;
+ }
+
+ Tracer(String tracerId, TracerPool tracerPool, Sampler[] curSamplers) {
+ this.tracerId = tracerId;
+ this.tracerPool = tracerPool;
+ this.threadContext = new ThreadLocalContext();
+ this.nullScope = new NullScope(this);
+ this.curSamplers = curSamplers;
+ }
+
+ public String getTracerId() {
+ return tracerId;
+ }
+
+ private TraceScope newScopeImpl(ThreadContext context, String description) {
+ Span span = new MilliSpan.Builder().
+ tracerId(tracerId).
+ begin(System.currentTimeMillis()).
+ description(description).
+ parents(EMPTY_PARENT_ARRAY).
+ spanId(SpanId.fromRandom()).
+ build();
+ return context.pushNewScope(this, span, null);
+ }
+
+ private TraceScope newScopeImpl(ThreadContext context, String description,
+ TraceScope parentScope) {
+ SpanId parentId = parentScope.getSpan().getSpanId();
+ Span span = new MilliSpan.Builder().
+ tracerId(tracerId).
+ begin(System.currentTimeMillis()).
+ description(description).
+ parents(new SpanId[] { parentId }).
+ spanId(parentId.newChildId()).
+ build();
+ return context.pushNewScope(this, span, parentScope);
+ }
+
+ private TraceScope newScopeImpl(ThreadContext context, String description,
+ SpanId parentId) {
+ Span span = new MilliSpan.Builder().
+ tracerId(tracerId).
+ begin(System.currentTimeMillis()).
+ description(description).
+ parents(new SpanId[] { parentId }).
+ spanId(parentId.newChildId()).
+ build();
+ return context.pushNewScope(this, span, null);
+ }
+
+ private TraceScope newScopeImpl(ThreadContext context, String description,
+ TraceScope parentScope, SpanId secondParentId) {
+ SpanId parentId = parentScope.getSpan().getSpanId();
+ Span span = new MilliSpan.Builder().
+ tracerId(tracerId).
+ begin(System.currentTimeMillis()).
+ description(description).
+ parents(new SpanId[] { parentId, secondParentId }).
+ spanId(parentId.newChildId()).
+ build();
+ return context.pushNewScope(this, span, parentScope);
+ }
+
+ /**
+ * Create a new trace scope.
+ *
+ * If there are no scopes above the current scope, we will apply our
+ * configured samplers. Otherwise, we will create a trace Span only if this thread
+ * is already tracing, or if the passed parentID was valid.
+ *
+ * @param description The description of the new span to create.
+ * @param parentId If this is a valid span ID, it will be added to
+ * the parents of the new span we create.
+ * @return The new trace scope.
+ */
+ public TraceScope newScope(String description, SpanId parentId) {
+ TraceScope parentScope = threadLocalScope.get();
+ ThreadContext context = threadContext.get();
+ if (parentScope != null) {
+ if (parentId.isValid() &&
+ (!parentId.equals(parentScope.getSpan().getSpanId()))) {
+ return newScopeImpl(context, description, parentScope, parentId);
+ } else {
+ return newScopeImpl(context, description, parentScope);
+ }
+ } else if (parentId.isValid()) {
+ return newScopeImpl(context, description, parentId);
+ }
+ if (!context.isTopLevel()) {
+ context.pushScope();
+ return nullScope;
+ }
+ if (!sample()) {
+ context.pushScope();
+ return nullScope;
+ }
+ return newScopeImpl(context, description);
+ }
+
+ /**
+ * Create a new trace scope.
+ *
+ * If there are no scopes above the current scope, we will apply our
+ * configured samplers. Otherwise, we will create a trace Span only if this thread
+ * is already tracing.
+ * @param description The description of the new span to create.
+ * @return The new trace scope.
+ */
+ public TraceScope newScope(String description) {
+ TraceScope parentScope = threadLocalScope.get();
+ ThreadContext context = threadContext.get();
+ if (parentScope != null) {
+ return newScopeImpl(context, description, parentScope);
+ }
+ if (!context.isTopLevel()) {
+ context.pushScope();
+ return nullScope;
+ }
+ if (!sample()) {
+ context.pushScope();
+ return nullScope;
+ }
+ return newScopeImpl(context, description);
+ }
+
+ /**
+ * Return a null trace scope.
+ */
+ public TraceScope newNullScope() {
+ ThreadContext context = threadContext.get();
+ context.pushScope();
+ return nullScope;
+ }
+
+ /**
+ * Wrap the callable in a TraceCallable, if tracing.
+ *
+ * @return The callable provided, wrapped if tracing, 'callable' if not.
+ */
+ public <V> Callable<V> wrap(Callable<V> callable, String description) {
+ TraceScope parentScope = threadLocalScope.get();
+ if (parentScope == null) {
+ return callable;
+ }
+ return new TraceCallable<V>(this, parentScope, callable, description);
+ }
+
+ /**
+ * Wrap the runnable in a TraceRunnable, if tracing
+ *
+ * @return The runnable provided, wrapped if tracing, 'runnable' if not.
+ */
+ public Runnable wrap(Runnable runnable, String description) {
+ TraceScope parentScope = threadLocalScope.get();
+ if (parentScope == null) {
+ return runnable;
+ }
+ return new TraceRunnable(this, parentScope, runnable, description);
+ }
+
+ public TraceExecutorService newTraceExecutorService(ExecutorService impl,
+ String scopeName) {
+ return new TraceExecutorService(this, scopeName, impl);
+ }
+
+ public TracerPool getTracerPool() {
+ if (tracerPool == null) {
+ throwClientError(toString() + " is closed.");
+ }
+ return tracerPool;
+ }
+
+ /**
+ * Returns an object that will trace all calls to itself.
+ */
+ @SuppressWarnings("unchecked")
+ <T, V> T createProxy(final T instance) {
+ final Tracer tracer = this;
+ InvocationHandler handler = new InvocationHandler() {
+ @Override
+ public Object invoke(Object obj, Method method, Object[] args)
+ throws Throwable {
+ TraceScope scope = tracer.newScope(method.getName());
+ try {
+ return method.invoke(instance, args);
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ throw ex;
+ } finally {
+ scope.close();
+ }
+ }
+ };
+ return (T) Proxy.newProxyInstance(instance.getClass().getClassLoader(),
+ instance.getClass().getInterfaces(), handler);
+ }
+
+ /**
+ * Return true if we should create a new top-level span.
+ *
+ * We will create the span if any configured sampler returns true.
+ */
+ private boolean sample() {
+ Sampler[] samplers = curSamplers;
+ for (Sampler sampler : samplers) {
+ if (sampler.next()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an array of all the current Samplers.
+ *
+ * Note that if the current Samplers change, those changes will not be
+ * reflected in this array. In other words, this array may be stale.
+ */
+ public Sampler[] getSamplers() {
+ return curSamplers;
+ }
+
+ /**
+ * Add a new Sampler.
+ *
+ * @param sampler The new sampler to add.
+ * You cannot add a particular Sampler object more
+ * than once. You may add multiple Sampler objects
+ * of the same type, although this is not recommended.
+ *
+ * @return True if the sampler was added; false if it already had
+ * been added earlier.
+ */
+ public synchronized boolean addSampler(Sampler sampler) {
+ if (tracerPool == null) {
+ throwClientError(toString() + " is closed.");
+ }
+ Sampler[] samplers = curSamplers;
+ for (int i = 0; i < samplers.length; i++) {
+ if (samplers[i] == sampler) {
+ return false;
+ }
+ }
+ Sampler[] newSamplers =
+ Arrays.copyOf(samplers, samplers.length + 1);
+ newSamplers[samplers.length] = sampler;
+ curSamplers = newSamplers;
+ return true;
+ }
+
+ /**
+ * Remove a SpanReceiver.
+ *
+ * @param sampler The sampler to remove.
+ */
+ public synchronized boolean removeSampler(Sampler sampler) {
+ if (tracerPool == null) {
+ throwClientError(toString() + " is closed.");
+ }
+ Sampler[] samplers = curSamplers;
+ for (int i = 0; i < samplers.length; i++) {
+ if (samplers[i] == sampler) {
+ Sampler[] newSamplers = new Sampler[samplers.length - 1];
+ System.arraycopy(samplers, 0, newSamplers, 0, i);
+ System.arraycopy(samplers, i + 1, newSamplers, i,
+ samplers.length - i - 1);
+ curSamplers = newSamplers;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void detachScope(TraceScope scope) {
+ TraceScope curScope = threadLocalScope.get();
+ if (curScope != scope) {
+ throwClientError("Can't detach TraceScope for " +
+ scope.getSpan().toJson() + " because it is not the current " +
+ "TraceScope in thread " + Thread.currentThread().getName());
+ }
+ ThreadContext context = threadContext.get();
+ context.popScope();
+ threadLocalScope.set(scope.getParent());
+ }
+
+ void reattachScope(TraceScope scope) {
+ TraceScope parent = threadLocalScope.get();
+ Tracer.threadLocalScope.set(scope);
+ ThreadContext context = threadContext.get();
+ context.pushScope();
+ scope.setParent(parent);
+ }
+
+ void closeScope(TraceScope scope) {
+ TraceScope curScope = threadLocalScope.get();
+ if (curScope != scope) {
+ throwClientError("Can't close TraceScope for " +
+ scope.getSpan().toJson() + " because it is not the current " +
+ "TraceScope in thread " + Thread.currentThread().getName());
+ }
+ if (tracerPool == null) {
+ throwClientError(toString() + " is closed.");
+ }
+ SpanReceiver[] receivers = tracerPool.getReceivers();
+ if (receivers == null) {
+ throwClientError(toString() + " is closed.");
+ }
+ ThreadContext context = threadContext.get();
+ context.popScope();
+ threadLocalScope.set(scope.getParent());
+ scope.setParent(null);
+ Span span = scope.getSpan();
+ span.stop();
+ for (SpanReceiver receiver : receivers) {
+ receiver.receiveSpan(span);
+ }
+ }
+
+ void popNullScope() {
+ TraceScope curScope = threadLocalScope.get();
+ if (curScope != null) {
+ throwClientError("Attempted to close an empty scope, but it was not " +
+ "the current thread scope in thread " +
+ Thread.currentThread().getName());
+ }
+ ThreadContext context = threadContext.get();
+ context.popScope();
+ }
+
+ public static Span getCurrentSpan() {
+ TraceScope curScope = threadLocalScope.get();
+ if (curScope == null) {
+ return null;
+ } else {
+ return curScope.getSpan();
+ }
+ }
+
+ public static SpanId getCurrentSpanId() {
+ TraceScope curScope = threadLocalScope.get();
+ if (curScope == null) {
+ return SpanId.INVALID;
+ } else {
+ return curScope.getSpan().getSpanId();
+ }
+ }
+
+ @Override
+ public synchronized void close() {
+ if (tracerPool == null) {
+ return;
+ }
+ curSamplers = new Sampler[0];
+ tracerPool.removeTracer(this);
+ }
+
+ /**
+ * Get the hash code of a Tracer object.
+ *
+ * This hash code is based on object identity.
+ * This is used in TracerPool to create a hash table of Tracers.
+ */
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ /**
+ * Compare two tracer objects.
+ *
+ * Tracer objects are always compared by object equality.
+ * This is used in TracerPool to create a hash table of Tracers.
+ */
+ @Override
+ public boolean equals(Object other) {
+ return (this == other);
+ }
+
+ @Override
+ public String toString() {
+ return "Tracer(" + tracerId + ")";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TracerId.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TracerId.java b/htrace-core4/src/main/java/org/apache/htrace/core/TracerId.java
new file mode 100644
index 0000000..da482fe
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TracerId.java
@@ -0,0 +1,294 @@
+/*
+ * 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.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.TreeSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The HTrace tracer ID.<p/>
+ *
+ * HTrace tracer IDs are created from format strings.
+ * Format strings contain variables which the TracerId class will
+ * replace with the correct values at runtime.<p/>
+ *
+ * <ul>
+ * <li>%{tname}: the tracer name supplied when creating the Tracer.</li>
+ * <li>%{pname}: the process name obtained from the JVM.</li>
+ * <li>%{ip}: will be replaced with an ip address.</li>
+ * <li>%{pid}: the numerical process ID from the operating system.</li>
+ * </ul><p/>
+ *
+ * For example, the string "%{pname}/%{ip}" will be replaced with something
+ * like: DataNode/192.168.0.1, assuming that the process' name is DataNode
+ * and its IP address is 192.168.0.1.<p/>
+ *
+ * ID strings can contain backslashes as escapes.
+ * For example, "\a" will map to "a". "\%{ip}" will map to the literal
+ * string "%{ip}", not the IP address. A backslash itself can be escaped by a
+ * preceding backslash.
+ */
+public final class TracerId {
+ private static final Log LOG = LogFactory.getLog(TracerId.class);
+
+ /**
+ * The configuration key to use for process id
+ */
+ public static final String TRACER_ID_KEY = "tracer.id";
+
+ /**
+ * The default tracer ID to use if no other ID is configured.
+ */
+ private static final String DEFAULT_TRACER_ID = "%{tname}/%{ip}";
+
+ private final String tracerName;
+
+ private final String tracerId;
+
+ public TracerId(HTraceConfiguration conf, String tracerName) {
+ this.tracerName = tracerName;
+ String fmt = conf.get(TRACER_ID_KEY, DEFAULT_TRACER_ID);
+ StringBuilder bld = new StringBuilder();
+ StringBuilder varBld = null;
+ boolean escaping = false;
+ int varSeen = 0;
+ for (int i = 0, len = fmt.length() ; i < len; i++) {
+ char c = fmt.charAt(i);
+ if (c == '\\') {
+ if (!escaping) {
+ escaping = true;
+ continue;
+ }
+ }
+ switch (varSeen) {
+ case 0:
+ if (c == '%') {
+ if (!escaping) {
+ varSeen = 1;
+ continue;
+ }
+ }
+ escaping = false;
+ varSeen = 0;
+ bld.append(c);
+ break;
+ case 1:
+ if (c == '{') {
+ if (!escaping) {
+ varSeen = 2;
+ varBld = new StringBuilder();
+ continue;
+ }
+ }
+ escaping = false;
+ varSeen = 0;
+ bld.append("%").append(c);
+ break;
+ default:
+ if (c == '}') {
+ if (!escaping) {
+ String var = varBld.toString();
+ bld.append(processShellVar(var));
+ varBld = null;
+ varSeen = 0;
+ continue;
+ }
+ }
+ escaping = false;
+ varBld.append(c);
+ varSeen++;
+ break;
+ }
+ }
+ if (varSeen > 0) {
+ LOG.warn("Unterminated process ID substitution variable at the end " +
+ "of format string " + fmt);
+ }
+ this.tracerId = bld.toString();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("ProcessID(fmt=" + fmt + "): computed process ID of \"" +
+ this.tracerId + "\"");
+ }
+ }
+
+ private String processShellVar(String var) {
+ if (var.equals("tname")) {
+ return tracerName;
+ } else if (var.equals("pname")) {
+ return getProcessName();
+ } else if (var.equals("ip")) {
+ return getBestIpString();
+ } else if (var.equals("pid")) {
+ return Long.valueOf(getOsPid()).toString();
+ } else {
+ LOG.warn("unknown ProcessID variable " + var);
+ return "";
+ }
+ }
+
+ static String getProcessName() {
+ String cmdLine = System.getProperty("sun.java.command");
+ if (cmdLine != null && !cmdLine.isEmpty()) {
+ String fullClassName = cmdLine.split("\\s+")[0];
+ String[] classParts = fullClassName.split("\\.");
+ cmdLine = classParts[classParts.length - 1];
+ }
+ return (cmdLine == null || cmdLine.isEmpty()) ? "Unknown" : cmdLine;
+ }
+
+ /**
+ * Get the best IP address that represents this node.<p/>
+ *
+ * This is complicated since nodes can have multiple network interfaces,
+ * and each network interface can have multiple IP addresses. What we're
+ * looking for here is an IP address that will serve to identify this node
+ * to HTrace. So we prefer site-local addresess (i.e. private ones on the
+ * LAN) to publicly routable interfaces. If there are multiple addresses
+ * to choose from, we select the one which comes first in textual sort
+ * order. This should ensure that we at least consistently call each node
+ * by a single name.
+ */
+ static String getBestIpString() {
+ Enumeration<NetworkInterface> ifaces;
+ try {
+ ifaces = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e) {
+ LOG.error("Error getting network interfaces", e);
+ return "127.0.0.1";
+ }
+ TreeSet<String> siteLocalCandidates = new TreeSet<String>();
+ TreeSet<String> candidates = new TreeSet<String>();
+ while (ifaces.hasMoreElements()) {
+ NetworkInterface iface = ifaces.nextElement();
+ for (Enumeration<InetAddress> addrs =
+ iface.getInetAddresses(); addrs.hasMoreElements();) {
+ InetAddress addr = addrs.nextElement();
+ if (!addr.isLoopbackAddress()) {
+ if (addr.isSiteLocalAddress()) {
+ siteLocalCandidates.add(addr.getHostAddress());
+ } else {
+ candidates.add(addr.getHostAddress());
+ }
+ }
+ }
+ }
+ if (!siteLocalCandidates.isEmpty()) {
+ return siteLocalCandidates.first();
+ }
+ if (!candidates.isEmpty()) {
+ return candidates.first();
+ }
+ return "127.0.0.1";
+ }
+
+ /**
+ * Get the process id from the operating system.<p/>
+ *
+ * Unfortunately, there is no simple method to get the process id in Java.
+ * The approach we take here is to use the shell method (see
+ * {TracerId#getOsPidFromShellPpid}) unless we are on Windows, where the
+ * shell is not available. On Windows, we use
+ * {TracerId#getOsPidFromManagementFactory}, which depends on some
+ * undocumented features of the JVM, but which doesn't require a shell.
+ */
+ static long getOsPid() {
+ if ((System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH)).
+ contains("windows")) {
+ return getOsPidFromManagementFactory();
+ } else {
+ return getOsPidFromShellPpid();
+ }
+ }
+
+ /**
+ * Get the process ID by executing a shell and printing the PPID (parent
+ * process ID).<p/>
+ *
+ * This method of getting the process ID doesn't depend on any undocumented
+ * features of the virtual machine, and should work on almost any UNIX
+ * operating system.
+ */
+ private static long getOsPidFromShellPpid() {
+ Process p = null;
+ StringBuilder sb = new StringBuilder();
+ try {
+ p = new ProcessBuilder("/usr/bin/env", "sh", "-c", "echo $PPID").
+ redirectErrorStream(true).start();
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(p.getInputStream()));
+ String line = "";
+ while ((line = reader.readLine()) != null) {
+ sb.append(line.trim());
+ }
+ int exitVal = p.waitFor();
+ if (exitVal != 0) {
+ throw new IOException("Process exited with error code " +
+ Integer.valueOf(exitVal).toString());
+ }
+ } catch (InterruptedException e) {
+ LOG.error("Interrupted while getting operating system pid from " +
+ "the shell.", e);
+ return 0L;
+ } catch (IOException e) {
+ LOG.error("Error getting operating system pid from the shell.", e);
+ return 0L;
+ } finally {
+ if (p != null) {
+ p.destroy();
+ }
+ }
+ try {
+ return Long.parseLong(sb.toString());
+ } catch (NumberFormatException e) {
+ LOG.error("Error parsing operating system pid from the shell.", e);
+ return 0L;
+ }
+ }
+
+ /**
+ * Get the process ID by looking at the name of the managed bean for the
+ * runtime system of the Java virtual machine.<p/>
+ *
+ * Although this is undocumented, in the Oracle JVM this name is of the form
+ * [OS_PROCESS_ID]@[HOSTNAME].
+ */
+ private static long getOsPidFromManagementFactory() {
+ try {
+ return Long.parseLong(ManagementFactory.getRuntimeMXBean().
+ getName().split("@")[0]);
+ } catch (NumberFormatException e) {
+ LOG.error("Failed to get the operating system process ID from the name " +
+ "of the managed bean for the JVM.", e);
+ return 0L;
+ }
+ }
+
+ public String get() {
+ return tracerId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/main/java/org/apache/htrace/core/TracerPool.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/main/java/org/apache/htrace/core/TracerPool.java b/htrace-core4/src/main/java/org/apache/htrace/core/TracerPool.java
new file mode 100644
index 0000000..26e39f5
--- /dev/null
+++ b/htrace-core4/src/main/java/org/apache/htrace/core/TracerPool.java
@@ -0,0 +1,285 @@
+/*
+ * 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.Arrays;
+import java.util.HashSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A pool of Tracer objects.
+ *
+ * There may be more than one {@link Tracer} running inside a single 'process'; for example,
+ * unit tests may spin up a DataNode, a NameNode, and HDFS clients all running in a single JVM
+ * instance, each with its own Tracer. TracerPool is where all Tracer instances register
+ * on creation so Tracers can coordinate around shared resources such as {@link SpanReceiver}
+ * instances. TracerPool takes care of properly cleaning up registered Tracer instances on shutdown.
+ */
+public class TracerPool {
+ private static final Log LOG = LogFactory.getLog(TracerPool.class);
+
+ /**
+ * The global pool of tracer objects.
+ *
+ * This is the pool that new tracers get put into by default.
+ */
+ static final TracerPool GLOBAL = new TracerPool("Global");
+
+ /**
+ * The shutdown hook which closes the Tracers in this pool when the process is
+ * shutting down.
+ */
+ private class SpanReceiverShutdownHook extends Thread {
+ SpanReceiverShutdownHook() {
+ setName("SpanReceiverShutdownHook");
+ setDaemon(false);
+ }
+
+ @Override
+ public void run() {
+ removeAndCloseAllSpanReceivers();
+ }
+ }
+
+ /**
+ * The name of this TracerPool.
+ */
+ private final String name;
+
+ /**
+ * The current span receivers which these tracers are using.
+ *
+ * Can be read locklessly. Must be written under the lock.
+ * The array itself should never be modified.
+ */
+ private volatile SpanReceiver[] curReceivers;
+
+ /**
+ * The currently installed shutdown hook, or null if no hook has been
+ * installed.
+ */
+ private SpanReceiverShutdownHook shutdownHook;
+
+ /**
+ * The current Tracers.
+ */
+ private final HashSet<Tracer> curTracers;
+
+ /**
+ * Get the global tracer pool.
+ */
+ public static TracerPool getGlobalTracerPool() {
+ return GLOBAL;
+ }
+
+ public TracerPool(String name) {
+ this.name = name;
+ this.shutdownHook = null;
+ this.curTracers = new HashSet<Tracer>();
+ this.curReceivers = new SpanReceiver[0];
+ }
+
+ /**
+ * Return the name of this TracerPool.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns an array of all the current span receivers.
+ *
+ * Note that if the current span receivers change, those changes will not be
+ * reflected in this array. In other words, this array may be stale.
+ */
+ public SpanReceiver[] getReceivers() {
+ return curReceivers;
+ }
+
+ /**
+ * Add a new span receiver.
+ *
+ * @param receiver The new receiver to add.
+ *
+ * @return True if the new receiver was added; false if it
+ * already was there.
+ */
+ public synchronized boolean addReceiver(SpanReceiver receiver) {
+ SpanReceiver[] receivers = curReceivers;
+ for (int i = 0; i < receivers.length; i++) {
+ if (receivers[i] == receiver) {
+ LOG.trace(toString() + ": can't add receiver " + receiver.toString() +
+ " since it is already in this pool.");
+ return false;
+ }
+ }
+ SpanReceiver[] newReceivers =
+ Arrays.copyOf(receivers, receivers.length + 1);
+ newReceivers[receivers.length] = receiver;
+ registerShutdownHookIfNeeded();
+ curReceivers = newReceivers;
+ LOG.trace(toString() + ": added receiver " + receiver.toString());
+ return true;
+ }
+
+ /**
+ * Register the shutdown hook if needed.
+ */
+ private synchronized void registerShutdownHookIfNeeded() {
+ if (shutdownHook != null) {
+ return;
+ }
+ shutdownHook = new SpanReceiverShutdownHook();
+ Runtime.getRuntime().addShutdownHook(shutdownHook);
+ LOG.trace(toString() + ": registered shutdown hook.");
+ }
+
+ /**
+ * Remove a span receiver.
+ *
+ * @param receiver The receiver to remove.
+ *
+ * @return True if the receiver was removed; false if it
+ * did not exist in this pool.
+ */
+ public synchronized boolean removeReceiver(SpanReceiver receiver) {
+ SpanReceiver[] receivers = curReceivers;
+ for (int i = 0; i < receivers.length; i++) {
+ if (receivers[i] == receiver) {
+ SpanReceiver[] newReceivers = new SpanReceiver[receivers.length - 1];
+ System.arraycopy(receivers, 0, newReceivers, 0, i);
+ System.arraycopy(receivers, i + 1, newReceivers, i,
+ receivers.length - i - 1);
+ curReceivers = newReceivers;
+ LOG.trace(toString() + ": removed receiver " + receiver.toString());
+ return true;
+ }
+ }
+ LOG.trace(toString() + ": can't remove receiver " + receiver.toString() +
+ " since it's not currently in this pool.");
+ return false;
+ }
+
+ /**
+ * Remove and close a span receiver.
+ *
+ * @param receiver The receiver to remove.
+ *
+ * @return True if the receiver was removed; false if it
+ * did not exist in this pool.
+ */
+ public boolean removeAndCloseReceiver(SpanReceiver receiver) {
+ if (!removeReceiver(receiver)) {
+ return false;
+ }
+ try {
+ LOG.trace(toString() + ": closing receiver " + receiver.toString());
+ receiver.close();
+ } catch (Throwable t) {
+ LOG.error(toString() + ": error closing " + receiver.toString(), t);
+ }
+ return true;
+ }
+
+ /**
+ * Remove and close all of the span receivers.
+ */
+ private synchronized void removeAndCloseAllSpanReceivers() {
+ SpanReceiver[] receivers = curReceivers;
+ curReceivers = new SpanReceiver[0];
+ for (SpanReceiver receiver : receivers) {
+ try {
+ LOG.trace(toString() + ": closing receiver " + receiver.toString());
+ receiver.close();
+ } catch (Throwable t) {
+ LOG.error(toString() + ": error closing " + receiver.toString(), t);
+ }
+ }
+ }
+
+ /**
+ * Given a SpanReceiver class name, return the existing instance of that span
+ * receiver, if possible; otherwise, invoke the callable to create a new
+ * instance.
+ *
+ * @param className The span receiver class name.
+ * @param conf The HTrace configuration.
+ * @param classLoader The class loader to use.
+ *
+ * @return The SpanReceiver.
+ */
+ public synchronized SpanReceiver loadReceiverType(String className,
+ HTraceConfiguration conf, ClassLoader classLoader) {
+ SpanReceiver[] receivers = curReceivers;
+ for (SpanReceiver receiver : receivers) {
+ if (receiver.getClass().getName().equals(className)) {
+ LOG.trace(toString() + ": returning a reference to receiver " +
+ receiver.toString());
+ return receiver;
+ }
+ }
+ LOG.trace(toString() + ": creating a new SpanReceiver of type " +
+ className);
+ SpanReceiver receiver = new SpanReceiver.Builder(conf).
+ className(className).
+ classLoader(classLoader).
+ build();
+ addReceiver(receiver);
+ return receiver;
+ }
+
+ /**
+ * Returns an array of all the current Tracers.
+ *
+ * Note that if the current Tracers change, those changes will not be
+ * reflected in this array. In other words, this array may be stale.
+ */
+ public synchronized Tracer[] getTracers() {
+ return curTracers.toArray(new Tracer[curTracers.size()]);
+ }
+
+ /**
+ * Add a new Tracer.
+ */
+ synchronized void addTracer(Tracer tracer) {
+ if (curTracers.add(tracer)) {
+ LOG.trace(toString() + ": adding tracer " + tracer.toString());
+ }
+ }
+
+ /**
+ * Remove a Tracer.
+ *
+ * If the Tracer removed was the last one, we will close all the SpanReceiver
+ * objects that we're managing.
+ */
+ synchronized void removeTracer(Tracer tracer) {
+ if (curTracers.remove(tracer)) {
+ LOG.trace(toString() + ": removing tracer " + tracer.toString());
+ if (curTracers.size() == 0) {
+ removeAndCloseAllSpanReceivers();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "TracerPool(" + name + ")";
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestBadClient.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestBadClient.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestBadClient.java
new file mode 100644
index 0000000..87ae8e9
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestBadClient.java
@@ -0,0 +1,205 @@
+/*
+ * 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.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestBadClient {
+ @After
+ public void clearBadState() {
+ // Clear the bad trace state so that we don't disrupt other unit tests
+ // that run in this JVM.
+ Tracer.threadLocalScope.set(null);
+ }
+
+ /**
+ * Test closing an outer scope when an inner one is still active.
+ */
+ @Test
+ public void TestClosingOuterScope() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestClosingOuterScopeTracer").
+ tracerPool(new TracerPool("TestClosingOuterScope")).
+ conf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
+ boolean gotException = false;
+ TraceScope outerScope = tracer.newScope("outer");
+ TraceScope innerScope = tracer.newScope("inner");
+ try {
+ outerScope.close();
+ } catch (RuntimeException e) {
+ assertThat(e.getMessage(),
+ containsString("it is not the current TraceScope"));
+ gotException = true;
+ }
+ assertTrue("Expected to get exception because of improper " +
+ "scope closure.", gotException);
+ innerScope.close();
+ tracer.close();
+ }
+
+ /**
+ * Test calling detach() two times on a scope object.
+ */
+ @Test
+ public void TestDoubleDetachIsCaught() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestDoubleDetach").
+ tracerPool(new TracerPool("TestDoubleDetachIsCaught")).
+ conf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
+ boolean gotException = false;
+ TraceScope myScope = tracer.newScope("myScope");
+ myScope.detach();
+ try {
+ myScope.detach();
+ } catch (RuntimeException e) {
+ assertThat(e.getMessage(),
+ containsString("it is already detached."));
+ gotException = true;
+ }
+ assertTrue("Expected to get exception because of double TraceScope " +
+ "detach.", gotException);
+ tracer.close();
+ }
+
+ /**
+ * Test calling detach() two times on a scope object.
+ */
+ @Test
+ public void TestDoubleDetachOnNullScope() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestDoubleDetachOnNullScope").
+ tracerPool(new TracerPool("TestDoubleDetachOnNullScope")).
+ conf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "NeverSampler")).build();
+ boolean gotException = false;
+ TraceScope myScope = tracer.newScope("myScope");
+ myScope.detach();
+ try {
+ myScope.detach();
+ } catch (RuntimeException e) {
+ assertThat(e.getMessage(),
+ containsString("it is already detached."));
+ gotException = true;
+ }
+ assertTrue("Expected to get exception because of double TraceScope " +
+ "detach on NullScope.", gotException);
+ tracer.close();
+ }
+
+ /**
+ * Test calling reattach() two times on a scope object.
+ */
+ @Test
+ public void TestDoubleReattachIsCaught() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestDoubleReattach").
+ tracerPool(new TracerPool("TestDoubleReattachIsCaught")).
+ conf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
+ boolean gotException = false;
+ TraceScope myScope = tracer.newScope("myScope");
+ myScope.detach();
+ myScope.reattach();
+ try {
+ myScope.reattach();
+ } catch (RuntimeException e) {
+ assertThat(e.getMessage(),
+ containsString("it is not detached."));
+ gotException = true;
+ }
+ assertTrue("Expected to get exception because of double TraceScope " +
+ "reattach.", gotException);
+ tracer.close();
+ }
+
+ private static class ScopeHolder {
+ TraceScope scope;
+
+ void set(TraceScope scope) {
+ this.scope = scope;
+ }
+ }
+
+ /**
+ * Test correctly passing spans between threads using detach().
+ */
+ @Test
+ public void TestPassingSpanBetweenThreads() throws Exception {
+ final Tracer tracer = new Tracer.Builder().
+ name("TestPassingSpanBetweenThreads").
+ tracerPool(new TracerPool("TestPassingSpanBetweenThreads")).
+ conf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "AlwaysSampler")).build();
+ POJOSpanReceiver receiver =
+ new POJOSpanReceiver(HTraceConfiguration.EMPTY);
+ tracer.getTracerPool().addReceiver(receiver);
+ final ScopeHolder scopeHolder = new ScopeHolder();
+ Thread th = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ TraceScope workerScope = tracer.newScope("workerSpan");
+ workerScope.detach();
+ scopeHolder.set(workerScope);
+ }
+ });
+ th.start();
+ th.join();
+ TraceScope workerScope = scopeHolder.scope;
+ SpanId workerScopeId = workerScope.getSpan().getSpanId();
+
+ // Create new scope whose parent is the worker thread's span.
+ workerScope.reattach();
+ TraceScope nested = tracer.newScope("nested");
+ nested.close();
+ // Create another span which also descends from the worker thread's span.
+ TraceScope nested2 = tracer.newScope("nested2");
+ nested2.close();
+
+ // Close the worker thread's span.
+ workerScope.close();
+
+ // We can create another descendant, even though the worker thread's span
+ // has been stopped.
+ TraceScope lateChildScope = tracer.newScope("lateChild", workerScopeId);
+ lateChildScope.close();
+ tracer.close();
+
+ TraceGraph traceGraph = new TraceGraph(receiver.getSpans());
+ Collection<Span> rootSpans =
+ traceGraph.getSpansByParent().find(SpanId.INVALID);
+ Assert.assertEquals(1, rootSpans.size());
+ Assert.assertEquals(workerScopeId,
+ rootSpans.iterator().next().getSpanId());
+ Collection<Span> childSpans =
+ traceGraph.getSpansByParent().find(workerScopeId);
+ Assert.assertEquals(3, childSpans.size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestCountSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestCountSampler.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestCountSampler.java
new file mode 100644
index 0000000..e26115d
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestCountSampler.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.htrace.core;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCountSampler {
+
+ @Test
+ public void testNext() {
+ CountSampler half = new CountSampler(HTraceConfiguration.
+ fromKeyValuePairs("sampler.frequency", "2"));
+ CountSampler hundred = new CountSampler(HTraceConfiguration.
+ fromKeyValuePairs("sampler.frequency", "100"));
+ int halfCount = 0;
+ int hundredCount = 0;
+ for (int i = 0; i < 200; i++) {
+ if (half.next())
+ halfCount++;
+ if (hundred.next())
+ hundredCount++;
+ }
+ Assert.assertEquals(2, hundredCount);
+ Assert.assertEquals(100, halfCount);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestHTrace.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestHTrace.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestHTrace.java
new file mode 100644
index 0000000..06ca189
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestHTrace.java
@@ -0,0 +1,130 @@
+/*
+ * 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.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.htrace.core.TraceGraph.SpansByParent;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestHTrace {
+ @Test
+ public void TestTracerCreateAndClose() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestSimpleScope").
+ tracerPool(new TracerPool("TestTracerCreateAndClose")).
+ conf(HTraceConfiguration.fromKeyValuePairs(
+ "sampler.classes", "AlwaysSampler")).
+ build();
+ POJOSpanReceiver receiver =
+ new POJOSpanReceiver(HTraceConfiguration.EMPTY);
+ tracer.getTracerPool().addReceiver(receiver);
+ tracer.close();
+ Assert.assertTrue(receiver.getSpans().isEmpty());
+ }
+
+ @Test
+ public void TestSimpleScope() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestSimpleScope").
+ tracerPool(new TracerPool("TestSimpleScope")).
+ conf(HTraceConfiguration.fromKeyValuePairs(
+ "sampler.classes", "AlwaysSampler")).
+ build();
+ POJOSpanReceiver receiver =
+ new POJOSpanReceiver(HTraceConfiguration.EMPTY);
+ tracer.getTracerPool().addReceiver(receiver);
+ TraceScope scope = tracer.newScope("Foo");
+ scope.close();
+ tracer.close();
+ Assert.assertEquals(1, receiver.getSpans().size());
+ Span span = receiver.getSpans().iterator().next();
+ Assert.assertEquals(0, span.getParents().length);
+ }
+
+ @Test
+ public void TestCreateSpans() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("TestCreateSpans").
+ tracerPool(new TracerPool("TestCreateSpans")).
+ conf(HTraceConfiguration.fromKeyValuePairs(
+ "sampler.classes", "AlwaysSampler")).
+ build();
+ POJOSpanReceiver receiver =
+ new POJOSpanReceiver(HTraceConfiguration.EMPTY);
+ tracer.getTracerPool().addReceiver(receiver);
+ TraceCreator traceCreator = new TraceCreator(tracer);
+ traceCreator.createSampleRpcTrace();
+ traceCreator.createSimpleTrace();
+ traceCreator.createThreadedTrace();
+ tracer.close();
+ TraceGraph traceGraph = new TraceGraph(receiver.getSpans());
+ Collection<Span> roots = traceGraph.getSpansByParent().find(SpanId.INVALID);
+ Assert.assertTrue("Trace tree must have roots", !roots.isEmpty());
+ Assert.assertEquals(3, roots.size());
+
+ Map<String, Span> descriptionToRootSpan = new HashMap<String, Span>();
+ for (Span root : roots) {
+ descriptionToRootSpan.put(root.getDescription(), root);
+ }
+
+ Assert.assertTrue(descriptionToRootSpan.keySet().contains(
+ TraceCreator.RPC_TRACE_ROOT));
+ Assert.assertTrue(descriptionToRootSpan.keySet().contains(
+ TraceCreator.SIMPLE_TRACE_ROOT));
+ Assert.assertTrue(descriptionToRootSpan.keySet().contains(
+ TraceCreator.THREADED_TRACE_ROOT));
+
+ SpansByParent spansByParentId = traceGraph.getSpansByParent();
+
+ Span rpcTraceRoot = descriptionToRootSpan.get(TraceCreator.RPC_TRACE_ROOT);
+ Assert.assertEquals(1, spansByParentId.find(rpcTraceRoot.getSpanId()).size());
+
+ Span rpcTraceChild1 = spansByParentId.find(rpcTraceRoot.getSpanId())
+ .iterator().next();
+ Assert.assertEquals(1, spansByParentId.find(rpcTraceChild1.getSpanId()).size());
+
+ Span rpcTraceChild2 = spansByParentId.find(rpcTraceChild1.getSpanId())
+ .iterator().next();
+ Assert.assertEquals(1, spansByParentId.find(rpcTraceChild2.getSpanId()).size());
+
+ Span rpcTraceChild3 = spansByParentId.find(rpcTraceChild2.getSpanId())
+ .iterator().next();
+ Assert.assertEquals(0, spansByParentId.find(rpcTraceChild3.getSpanId()).size());
+ }
+
+ @Test(timeout=60000)
+ public void testRootSpansHaveNonZeroSpanId() throws Exception {
+ Tracer tracer = new Tracer.Builder().
+ name("testRootSpansHaveNonZeroSpanId").
+ tracerPool(new TracerPool("testRootSpansHaveNonZeroSpanId")).
+ conf(HTraceConfiguration.fromKeyValuePairs(
+ "sampler.classes", "AlwaysSampler")).build();
+ TraceScope scope = tracer.
+ newScope("myRootSpan", new SpanId(100L, 200L));
+ Assert.assertNotNull(scope);
+ Assert.assertEquals("myRootSpan", scope.getSpan().getDescription());
+ Assert.assertTrue(scope.getSpan().getSpanId().isValid());
+ Assert.assertEquals(100L, scope.getSpan().getSpanId().getHigh());
+ Assert.assertNotEquals(0L, scope.getSpan().getSpanId().getLow());
+ scope.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java
new file mode 100644
index 0000000..7ca897f
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestHTraceConfiguration.java
@@ -0,0 +1,62 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class TestHTraceConfiguration {
+ @Test
+ public void testGetBoolean() throws Exception {
+
+ Map<String, String> m = new HashMap<String, String>();
+ m.put("testTrue", " True");
+ m.put("testFalse", "falsE ");
+ HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
+
+ // Tests for value being there
+ assertTrue(configuration.getBoolean("testTrue", false));
+ assertFalse(configuration.getBoolean("testFalse", true));
+
+ // Test for absent
+ assertTrue(configuration.getBoolean("absent", true));
+ assertFalse(configuration.getBoolean("absent", false));
+ }
+
+ @Test
+ public void testGetInt() throws Exception {
+ Map<String, String> m = new HashMap<String, String>();
+ m.put("a", "100");
+ m.put("b", "0");
+ m.put("c", "-100");
+ m.put("d", "5");
+
+ HTraceConfiguration configuration = HTraceConfiguration.fromMap(m);
+ assertEquals(100, configuration.getInt("a", -999));
+ assertEquals(0, configuration.getInt("b", -999));
+ assertEquals(-100, configuration.getInt("c", -999));
+ assertEquals(5, configuration.getInt("d", -999));
+ assertEquals(-999, configuration.getInt("absent", -999));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java
new file mode 100644
index 0000000..9388707
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestLocalFileSpanReceiver.java
@@ -0,0 +1,65 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+public class TestLocalFileSpanReceiver {
+ @Test
+ public void testUniqueLocalTraceFileName() {
+ String filename1 = LocalFileSpanReceiver.getUniqueLocalTraceFileName();
+ String filename2 = LocalFileSpanReceiver.getUniqueLocalTraceFileName();
+ boolean eq = filename1.equals(filename2);
+ if (System.getProperty("os.name").startsWith("Linux")) {
+ // ${java.io.tmpdir}/[pid]
+ assertTrue(eq);
+ } else {
+ // ${java.io.tmpdir}/[random UUID]
+ assertFalse(eq);
+ }
+ }
+
+ @Test
+ public void testWriteToLocalFile() throws IOException {
+ String traceFileName = LocalFileSpanReceiver.getUniqueLocalTraceFileName();
+ Tracer tracer = new Tracer.Builder().
+ name("testWriteToLocalFileTracer").
+ tracerPool(new TracerPool("testWriteToLocalFile")).
+ conf(HTraceConfiguration.fromKeyValuePairs(
+ "sampler.classes", "AlwaysSampler",
+ "span.receiver.classes", LocalFileSpanReceiver.class.getName(),
+ "local.file.span.receiver.path", traceFileName,
+ "tracer.id", "%{tname}")).
+ build();
+ TraceScope scope = tracer.newScope("testWriteToLocalFile");
+ scope.close();
+ tracer.close();
+
+ ObjectMapper mapper = new ObjectMapper();
+ MilliSpan span = mapper.readValue(new File(traceFileName), MilliSpan.class);
+ assertEquals("testWriteToLocalFile", span.getDescription());
+ assertEquals("testWriteToLocalFileTracer", span.getTracerId());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestMilliSpan.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestMilliSpan.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestMilliSpan.java
new file mode 100644
index 0000000..7ce1fdb
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestMilliSpan.java
@@ -0,0 +1,145 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class TestMilliSpan {
+ private void compareSpans(Span expected, Span got) throws Exception {
+ assertEquals(expected.getStartTimeMillis(), got.getStartTimeMillis());
+ assertEquals(expected.getStopTimeMillis(), got.getStopTimeMillis());
+ assertEquals(expected.getDescription(), got.getDescription());
+ assertEquals(expected.getSpanId(), got.getSpanId());
+ assertEquals(expected.getTracerId(), got.getTracerId());
+ assertTrue(Arrays.equals(expected.getParents(), got.getParents()));
+ Map<String, String> expectedT = expected.getKVAnnotations();
+ Map<String, String> gotT = got.getKVAnnotations();
+ if (expectedT == null) {
+ assertEquals(null, gotT);
+ } else {
+ assertEquals(expectedT.size(), gotT.size());
+ for (String key : expectedT.keySet()) {
+ assertEquals(expectedT.get(key), gotT.get(key));
+ }
+ }
+ List<TimelineAnnotation> expectedTimeline =
+ expected.getTimelineAnnotations();
+ List<TimelineAnnotation> gotTimeline =
+ got.getTimelineAnnotations();
+ if (expectedTimeline == null) {
+ assertEquals(null, gotTimeline);
+ } else {
+ assertEquals(expectedTimeline.size(), gotTimeline.size());
+ Iterator<TimelineAnnotation> iter = gotTimeline.iterator();
+ for (TimelineAnnotation expectedAnn : expectedTimeline) {
+ TimelineAnnotation gotAnn = iter.next();
+ assertEquals(expectedAnn.getMessage(), gotAnn.getMessage());
+ assertEquals(expectedAnn.getTime(), gotAnn.getTime());
+ }
+ }
+ }
+
+ @Test
+ public void testJsonSerialization() throws Exception {
+ MilliSpan span = new MilliSpan.Builder().
+ description("foospan").
+ begin(123L).
+ end(456L).
+ parents(new SpanId[] { new SpanId(7L, 7L) }).
+ tracerId("b2404.halxg.com:8080").
+ spanId(new SpanId(7L, 8L)).
+ build();
+ String json = span.toJson();
+ MilliSpan dspan = MilliSpan.fromJson(json);
+ compareSpans(span, dspan);
+ }
+
+ @Test
+ public void testJsonSerializationWithNegativeLongValue() throws Exception {
+ MilliSpan span = new MilliSpan.Builder().
+ description("foospan").
+ begin(-1L).
+ end(-1L).
+ parents(new SpanId[] { new SpanId(-1L, -1L) }).
+ tracerId("b2404.halxg.com:8080").
+ spanId(new SpanId(-1L, -2L)).
+ build();
+ String json = span.toJson();
+ MilliSpan dspan = MilliSpan.fromJson(json);
+ compareSpans(span, dspan);
+ }
+
+ @Test
+ public void testJsonSerializationWithRandomLongValue() throws Exception {
+ SpanId parentId = SpanId.fromRandom();
+ MilliSpan span = new MilliSpan.Builder().
+ description("foospan").
+ begin(ThreadLocalRandom.current().nextLong()).
+ end(ThreadLocalRandom.current().nextLong()).
+ parents(new SpanId[] { parentId }).
+ tracerId("b2404.halxg.com:8080").
+ spanId(parentId.newChildId()).
+ build();
+ String json = span.toJson();
+ MilliSpan dspan = MilliSpan.fromJson(json);
+ compareSpans(span, dspan);
+ }
+
+ @Test
+ public void testJsonSerializationWithOptionalFields() throws Exception {
+ MilliSpan.Builder builder = new MilliSpan.Builder().
+ description("foospan").
+ begin(300).
+ end(400).
+ parents(new SpanId[] { }).
+ tracerId("b2408.halxg.com:8080").
+ spanId(new SpanId(111111111L, 111111111L));
+ Map<String, String> traceInfo = new HashMap<String, String>();
+ traceInfo.put("abc", "123");
+ traceInfo.put("def", "456");
+ builder.traceInfo(traceInfo);
+ List<TimelineAnnotation> timeline = new LinkedList<TimelineAnnotation>();
+ timeline.add(new TimelineAnnotation(310L, "something happened"));
+ timeline.add(new TimelineAnnotation(380L, "something else happened"));
+ timeline.add(new TimelineAnnotation(390L, "more things"));
+ builder.timeline(timeline);
+ MilliSpan span = builder.build();
+ String json = span.toJson();
+ MilliSpan dspan = MilliSpan.fromJson(json);
+ compareSpans(span, dspan);
+ }
+
+ @Test
+ public void testJsonSerializationWithFieldsNotSet() throws Exception {
+ MilliSpan span = new MilliSpan.Builder().build();
+ String json = span.toJson();
+ MilliSpan dspan = MilliSpan.fromJson(json);
+ compareSpans(span, dspan);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestNullScope.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestNullScope.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestNullScope.java
new file mode 100644
index 0000000..c8ed7f1
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestNullScope.java
@@ -0,0 +1,43 @@
+/*
+ * 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.junit.Assert;
+import org.junit.Test;
+
+public class TestNullScope {
+ private void verifyNullScope(TraceScope scope) {
+ Assert.assertTrue(null == scope.getSpan());
+ Assert.assertFalse(scope.detached);
+ scope.detach();
+ Assert.assertTrue(scope.detached);
+ scope.reattach();
+ Assert.assertFalse(scope.detached);
+ scope.close();
+ }
+
+ @Test
+ public void testNullScope() {
+ Tracer tracer = new Tracer.Builder().
+ name("testNullScope").
+ tracerPool(new TracerPool("testNullScope")).
+ conf(HTraceConfiguration.EMPTY).
+ build();
+ verifyNullScope(tracer.newScope("testNullScope"));
+ verifyNullScope(tracer.newNullScope());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestSampler.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestSampler.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestSampler.java
new file mode 100644
index 0000000..2305d9f
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestSampler.java
@@ -0,0 +1,100 @@
+/*
+ * 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.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestSampler {
+ private Sampler[] getSamplersFromConf(HTraceConfiguration conf) {
+ Tracer tracer = new Tracer.Builder().
+ name("MyTracer").
+ tracerPool(new TracerPool("getSamplersFromConf")).
+ conf(conf).
+ build();
+ Sampler[] samplers = tracer.getSamplers();
+ tracer.close();
+ return samplers;
+ }
+
+ private void checkArrayContains(List<Class<? extends Sampler>> expected,
+ Sampler[] samplers) {
+ for (Iterator<Class<? extends Sampler>> iter = expected.iterator();
+ iter.hasNext(); ) {
+ Class<? extends Sampler> samplerClass = iter.next();
+ boolean found = false;
+ for (int i = 0; i < samplers.length; i++) {
+ if (samplers[i] != null) {
+ if (samplers[i].getClass().equals(samplerClass)) {
+ samplers[i] = null;
+ found = true;
+ break;
+ }
+ }
+ }
+ Assert.assertTrue("Failed to find sampler class " +
+ samplerClass.getName(), found);
+ }
+ for (int i = 0; i < samplers.length; i++) {
+ if (samplers[i] != null) {
+ Assert.fail("Got extra sampler of type " +
+ samplers.getClass().getName());
+ }
+ }
+ }
+
+ private void checkArrayContains(Class<? extends Sampler> expected, Sampler[] samplers) {
+ LinkedList<Class<? extends Sampler>> expectedList =
+ new LinkedList<Class<? extends Sampler>>();
+ expectedList.add(expected);
+ checkArrayContains(expectedList, samplers);
+ }
+
+ @Test
+ public void testTracerBuilderCreatesCorrectSamplers() {
+ Sampler[] samplers = getSamplersFromConf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "AlwaysSampler"));
+ checkArrayContains(AlwaysSampler.class, samplers);
+
+ samplers = getSamplersFromConf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "NeverSampler"));
+ checkArrayContains(NeverSampler.class, samplers);
+
+ samplers = getSamplersFromConf(HTraceConfiguration.
+ fromKeyValuePairs("sampler.classes", "NonExistentSampler"));
+ Assert.assertEquals(0, samplers.length);
+
+ samplers = getSamplersFromConf(HTraceConfiguration.EMPTY);
+ Assert.assertEquals(0, samplers.length);
+ }
+
+ @Test
+ public void testAlwaysSampler() {
+ AlwaysSampler sampler = new AlwaysSampler(HTraceConfiguration.EMPTY);
+ Assert.assertTrue(sampler.next());
+ }
+
+ @Test
+ public void testNeverSampler() {
+ NeverSampler sampler = new NeverSampler(HTraceConfiguration.EMPTY);
+ Assert.assertTrue(!sampler.next());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanId.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanId.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanId.java
new file mode 100644
index 0000000..bb57368
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanId.java
@@ -0,0 +1,72 @@
+/*
+ * 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.Random;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestSpanId {
+ private void testRoundTrip(SpanId id) throws Exception {
+ String str = id.toString();
+ SpanId id2 = SpanId.fromString(str);
+ Assert.assertEquals(id, id2);
+ }
+
+ @Test
+ public void testToStringAndFromString() throws Exception {
+ testRoundTrip(SpanId.INVALID);
+ testRoundTrip(new SpanId(0x1234567812345678L, 0x1234567812345678L));
+ testRoundTrip(new SpanId(0xf234567812345678L, 0xf234567812345678L));
+ testRoundTrip(new SpanId(0xffffffffffffffffL, 0xffffffffffffffffL));
+ Random rand = new Random(12345);
+ for (int i = 0; i < 100; i++) {
+ testRoundTrip(new SpanId(rand.nextLong(), rand.nextLong()));
+ }
+ }
+
+ @Test
+ public void testValidAndInvalidIds() throws Exception {
+ Assert.assertFalse(SpanId.INVALID.isValid());
+ Assert.assertTrue(
+ new SpanId(0x1234567812345678L, 0x1234567812345678L).isValid());
+ Assert.assertTrue(
+ new SpanId(0xf234567812345678L, 0xf234567812345678L).isValid());
+ }
+
+ private void expectLessThan(SpanId a, SpanId b) throws Exception {
+ int cmp = a.compareTo(b);
+ Assert.assertTrue("Expected " + a + " to be less than " + b,
+ (cmp < 0));
+ int cmp2 = b.compareTo(a);
+ Assert.assertTrue("Expected " + b + " to be greater than " + a,
+ (cmp2 > 0));
+ }
+
+ @Test
+ public void testIdComparisons() throws Exception {
+ expectLessThan(new SpanId(0x0000000000000001L, 0x0000000000000001L),
+ new SpanId(0x0000000000000001L, 0x0000000000000002L));
+ expectLessThan(new SpanId(0x0000000000000001L, 0x0000000000000001L),
+ new SpanId(0x0000000000000002L, 0x0000000000000000L));
+ expectLessThan(SpanId.INVALID,
+ new SpanId(0xffffffffffffffffL, 0xffffffffffffffffL));
+ expectLessThan(new SpanId(0x1234567812345678L, 0x1234567812345678L),
+ new SpanId(0x1234567812345678L, 0xf234567812345678L));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/3c20489f/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java
----------------------------------------------------------------------
diff --git a/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java b/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java
new file mode 100644
index 0000000..b97d624
--- /dev/null
+++ b/htrace-core4/src/test/java/org/apache/htrace/core/TestSpanReceiverBuilder.java
@@ -0,0 +1,127 @@
+/*
+ * 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 org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class TestSpanReceiverBuilder {
+ private static final Log LOG =
+ LogFactory.getLog(TestSpanReceiverBuilder.class);
+
+ private List<SpanReceiver> createSpanReceivers(String classes) {
+ Tracer tracer = new Tracer.Builder().
+ name("MyTracer").
+ tracerPool(new TracerPool("createSpanReceivers")).
+ conf(HTraceConfiguration.fromKeyValuePairs(
+ "span.receiver.classes", classes)).
+ build();
+ SpanReceiver[] receivers = tracer.getTracerPool().getReceivers();
+ tracer.close();
+ LinkedList<SpanReceiver> receiverList = new LinkedList<SpanReceiver>();
+ for (SpanReceiver item: receivers) {
+ receiverList.add(item);
+ }
+ return receiverList;
+ }
+
+ @Test
+ public void TestCreateStandardSpanReceivers() {
+ List<SpanReceiver> receivers;
+ receivers = createSpanReceivers("");
+ Assert.assertTrue(receivers.isEmpty());
+ receivers = createSpanReceivers("POJOSpanReceiver");
+ Assert.assertTrue(receivers.get(0).getClass().getName().
+ equals("org.apache.htrace.core.POJOSpanReceiver"));
+ receivers = createSpanReceivers(
+ "org.apache.htrace.core.StandardOutSpanReceiver");
+ Assert.assertTrue(receivers.get(0).getClass().getName().
+ equals("org.apache.htrace.core.StandardOutSpanReceiver"));
+ receivers = createSpanReceivers(
+ "POJOSpanReceiver;StandardOutSpanReceiver");
+ Assert.assertEquals(2, receivers.size());
+ for (Iterator<SpanReceiver> iter = receivers.iterator(); iter.hasNext();) {
+ SpanReceiver receiver = iter.next();
+ if (receiver.getClass().getName().equals(
+ "org.apache.htrace.core.POJOSpanReceiver")) {
+ iter.remove();
+ break;
+ }
+ }
+ for (Iterator<SpanReceiver> iter = receivers.iterator(); iter.hasNext();) {
+ SpanReceiver receiver = iter.next();
+ if (receiver.getClass().getName().equals(
+ "org.apache.htrace.core.StandardOutSpanReceiver")) {
+ iter.remove();
+ break;
+ }
+ }
+ Assert.assertEquals(0, receivers.size());
+ }
+
+ public static class GoodSpanReceiver extends SpanReceiver {
+ public GoodSpanReceiver(HTraceConfiguration conf) {
+ }
+
+ @Override
+ public void receiveSpan(Span span) {
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ }
+
+ public static class BadSpanReceiver extends SpanReceiver {
+ public BadSpanReceiver(HTraceConfiguration conf) {
+ throw new RuntimeException("Can't create BadSpanReceiver");
+ }
+
+ @Override
+ public void receiveSpan(Span span) {
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ }
+
+ /**
+ * Test trying to create a SpanReceiver that experiences an error in the
+ * constructor.
+ */
+ @Test
+ public void testGetSpanReceiverWithConstructorError() throws Exception {
+ List<SpanReceiver> receivers;
+ receivers = createSpanReceivers(
+ GoodSpanReceiver.class.getName());
+ Assert.assertEquals(1, receivers.size());
+ Assert.assertTrue(receivers.get(0).getClass().getName().
+ contains("GoodSpanReceiver"));
+ receivers = createSpanReceivers(
+ BadSpanReceiver.class.getName());
+ Assert.assertEquals(0, receivers.size());
+ }
+}