HTRACE-40. MilliSpanDeserializer throws NumberFormatException when Span has negative Long value (Long Zhou via Colin P. McCabe)
diff --git a/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java b/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java
index 77e289e..7f3e81a 100644
--- a/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java
+++ b/htrace-core/src/main/java/org/apache/htrace/impl/MilliSpan.java
@@ -30,6 +30,7 @@
import java.io.IOException;
import java.io.StringWriter;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -282,6 +283,10 @@
return writer.toString();
}
+ private static long parseUnsignedLong(String s) {
+ return new BigInteger(s, 16).longValue();
+ }
+
public static class MilliSpanDeserializer
extends JsonDeserializer<MilliSpan> {
@Override
@@ -292,15 +297,15 @@
builder.begin(root.get("b").asLong()).
end(root.get("e").asLong()).
description(root.get("d").asText()).
- traceId(Long.parseLong(root.get("i").asText(), 16)).
- spanId(Long.parseLong(root.get("s").asText(), 16)).
+ traceId(parseUnsignedLong(root.get("i").asText())).
+ spanId(parseUnsignedLong(root.get("s").asText())).
processId(root.get("r").asText());
JsonNode parentsNode = root.get("p");
LinkedList<Long> parents = new LinkedList<Long>();
for (Iterator<JsonNode> iter = parentsNode.elements();
iter.hasNext(); ) {
JsonNode parentIdNode = iter.next();
- parents.add(Long.parseLong(parentIdNode.asText(), 16));
+ parents.add(parseUnsignedLong(parentIdNode.asText()));
}
builder.parents(parents);
JsonNode traceInfoNode = root.get("n");
diff --git a/htrace-core/src/test/java/org/apache/htrace/impl/TestMilliSpan.java b/htrace-core/src/test/java/org/apache/htrace/impl/TestMilliSpan.java
index 908e74e..677ec61 100644
--- a/htrace-core/src/test/java/org/apache/htrace/impl/TestMilliSpan.java
+++ b/htrace-core/src/test/java/org/apache/htrace/impl/TestMilliSpan.java
@@ -24,11 +24,13 @@
import org.apache.htrace.TimelineAnnotation;
import org.junit.Test;
+import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Random;
public class TestMilliSpan {
private void compareSpans(Span expected, Span got) throws Exception {
@@ -93,6 +95,39 @@
}
@Test
+ public void testJsonSerializationWithNegativeLongValue() throws Exception {
+ MilliSpan span = new MilliSpan.Builder().
+ description("foospan").
+ begin(-1L).
+ end(-1L).
+ parents(new long[] { -1L }).
+ processId("b2404.halxg.com:8080").
+ spanId(-1L).
+ traceId(-1L).build();
+ String json = span.toJson();
+ ObjectMapper mapper = new ObjectMapper();
+ MilliSpan dspan = mapper.readValue(json, MilliSpan.class);
+ compareSpans(span, dspan);
+ }
+
+ @Test
+ public void testJsonSerializationWithRandomLongValue() throws Exception {
+ Random random = new SecureRandom();
+ MilliSpan span = new MilliSpan.Builder().
+ description("foospan").
+ begin(random.nextLong()).
+ end(random.nextLong()).
+ parents(new long[] { random.nextLong() }).
+ processId("b2404.halxg.com:8080").
+ spanId(random.nextLong()).
+ traceId(random.nextLong()).build();
+ String json = span.toJson();
+ ObjectMapper mapper = new ObjectMapper();
+ MilliSpan dspan = mapper.readValue(json, MilliSpan.class);
+ compareSpans(span, dspan);
+ }
+
+ @Test
public void testJsonSerializationWithOptionalFields() throws Exception {
MilliSpan.Builder builder = new MilliSpan.Builder().
description("foospan").