| /* |
| * 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.zipkin; |
| |
| import com.twitter.zipkin.gen.zipkinCoreConstants; |
| |
| import org.apache.htrace.core.HTraceConfiguration; |
| import org.apache.htrace.core.MilliSpan; |
| import org.apache.htrace.core.POJOSpanReceiver; |
| import org.apache.htrace.core.Span; |
| import org.apache.htrace.core.SpanId; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import java.io.IOException; |
| import java.util.Collection; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| /** |
| * Creates HTrace and then convert it to Zipkin trace and checks whether it is a valid span or not. |
| */ |
| public class TestHTraceSpanToZipkinSpan { |
| private static final String ROOT_SPAN_DESC = "ROOT"; |
| |
| @Test |
| public void testHTraceToZipkin() throws IOException { |
| Span rootSpan = new MilliSpan.Builder(). |
| description(ROOT_SPAN_DESC). |
| parents(new SpanId[] { } ). |
| spanId(new SpanId(100, 100)). |
| tracerId("test"). |
| begin(System.currentTimeMillis()). |
| build(); |
| Span innerOne = rootSpan.child("Some good work"); |
| Span innerTwo = innerOne.child("Some more good work"); |
| innerTwo.stop(); |
| innerOne.stop(); |
| rootSpan.addKVAnnotation("foo", "bar"); |
| rootSpan.addTimelineAnnotation("timeline"); |
| rootSpan.stop(); |
| |
| for (Span s : new Span[] {rootSpan, innerOne, innerTwo}) { |
| com.twitter.zipkin.gen.Span zs = |
| new HTraceToZipkinConverter(12345, (short) 12).convert(s); |
| assertSpansAreEquivalent(s, zs); |
| } |
| } |
| |
| @Test |
| public void testHTraceAnnotationTimestamp() throws IOException, InterruptedException { |
| |
| String tracerId = "testHTraceAnnotationTimestamp"; |
| long startTime = System.currentTimeMillis() * 1000; |
| Span ms = new MilliSpan.Builder(). |
| description(tracerId).parents(new SpanId[] { }). |
| spanId(new SpanId(2L, 2L)). |
| tracerId(tracerId). |
| begin(System.currentTimeMillis()). |
| build(); |
| |
| Thread.sleep(500); |
| long annoStartTime = System.currentTimeMillis() * 1000; |
| Thread.sleep(500); |
| ms.addTimelineAnnotation("anno"); |
| Thread.sleep(500); |
| long annoEndTime = System.currentTimeMillis() * 1000; |
| Thread.sleep(500); |
| ms.stop(); |
| long endTime = System.currentTimeMillis() * 1000; |
| |
| |
| |
| com.twitter.zipkin.gen.Span zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms); |
| |
| // Check to make sure that all times are in the proper order. |
| for (com.twitter.zipkin.gen.Annotation annotation : zs.getAnnotations()) { |
| // CS and SR should be before the annotation |
| // the annotation should be in between annotationStart and annotationEnd times |
| // SS and CR should be after annotationEnd and before endtime. |
| if (annotation.getValue().equals(zipkinCoreConstants.CLIENT_SEND) |
| || annotation.getValue().equals(zipkinCoreConstants.SERVER_RECV)) { |
| assertTrue(startTime <= annotation.getTimestamp()); |
| assertTrue(annotation.getTimestamp() <= annoStartTime); |
| } else if (annotation.getValue().equals(zipkinCoreConstants.CLIENT_RECV) |
| || annotation.getValue().equals(zipkinCoreConstants.SERVER_SEND)) { |
| assertTrue(annoEndTime <= annotation.getTimestamp()); |
| assertTrue(annotation.getTimestamp() <= endTime); |
| } else { |
| assertTrue(annoStartTime <= annotation.getTimestamp()); |
| assertTrue(annotation.getTimestamp() <= annoEndTime); |
| assertTrue(annotation.getTimestamp() <= endTime); |
| } |
| } |
| } |
| |
| @Test |
| public void testHTraceDefaultPort() throws IOException { |
| MilliSpan ms = new MilliSpan.Builder().description("test"). |
| parents(new SpanId[] { new SpanId(2L, 2L) }). |
| spanId(new SpanId(2L, 3L)). |
| tracerId("hmaster"). |
| begin(System.currentTimeMillis()). |
| build(); |
| com.twitter.zipkin.gen.Span zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms); |
| for (com.twitter.zipkin.gen.Annotation annotation:zs.getAnnotations()) { |
| assertEquals((short)60000, annotation.getHost().getPort()); |
| } |
| |
| // make sure it's all lower cased |
| ms = new MilliSpan.Builder().description("test"). |
| parents(new SpanId[] {new SpanId(2, 2)}). |
| spanId(new SpanId(2, 3)). |
| tracerId("HregIonServer"). |
| begin(System.currentTimeMillis()). |
| build(); |
| zs = new HTraceToZipkinConverter(12345, (short) -1).convert(ms); |
| for (com.twitter.zipkin.gen.Annotation annotation:zs.getAnnotations()) { |
| assertEquals((short)60020, annotation.getHost().getPort()); |
| } |
| } |
| |
| private void assertSpansAreEquivalent(Span s, com.twitter.zipkin.gen.Span zs) { |
| assertTrue("zipkin doesn't support multiple parents to a single span.", |
| s.getParents().length <= 1); |
| if (s.getParents().length == 1) { |
| assertEquals(s.getParents()[0].getLow(), zs.getParent_id()); |
| } |
| assertEquals(s.getSpanId().getLow(), zs.getId()); |
| Assert.assertNotNull(zs.getAnnotations()); |
| if (ROOT_SPAN_DESC.equals(zs.getName())) { |
| assertEquals(5, zs.getAnnotations().size());// two start, two stop + one timeline annotation |
| assertEquals(1, zs.getBinary_annotations().size()); |
| } else { |
| assertEquals(4, zs.getAnnotations().size()); |
| } |
| } |
| } |