Home | History | Annotate | Download | only in jaeger
      1 /*
      2  * Copyright 2018, OpenCensus Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package io.opencensus.exporter.trace.jaeger;
     18 
     19 import static com.google.common.truth.Truth.assertThat;
     20 import static java.util.Collections.singletonList;
     21 import static java.util.concurrent.TimeUnit.MILLISECONDS;
     22 import static org.mockito.Matchers.eq;
     23 import static org.mockito.Mockito.mock;
     24 import static org.mockito.Mockito.verify;
     25 
     26 import com.google.common.collect.ImmutableMap;
     27 import com.google.common.collect.Lists;
     28 import com.uber.jaeger.exceptions.SenderException;
     29 import com.uber.jaeger.senders.HttpSender;
     30 import com.uber.jaeger.thriftjava.Log;
     31 import com.uber.jaeger.thriftjava.Process;
     32 import com.uber.jaeger.thriftjava.Span;
     33 import com.uber.jaeger.thriftjava.SpanRef;
     34 import com.uber.jaeger.thriftjava.SpanRefType;
     35 import com.uber.jaeger.thriftjava.Tag;
     36 import com.uber.jaeger.thriftjava.TagType;
     37 import io.opencensus.common.Timestamp;
     38 import io.opencensus.trace.Annotation;
     39 import io.opencensus.trace.AttributeValue;
     40 import io.opencensus.trace.Link;
     41 import io.opencensus.trace.MessageEvent;
     42 import io.opencensus.trace.SpanContext;
     43 import io.opencensus.trace.SpanId;
     44 import io.opencensus.trace.Status;
     45 import io.opencensus.trace.TraceId;
     46 import io.opencensus.trace.TraceOptions;
     47 import io.opencensus.trace.export.SpanData;
     48 import java.util.List;
     49 import org.junit.Test;
     50 import org.junit.runner.RunWith;
     51 import org.mockito.ArgumentCaptor;
     52 import org.mockito.Captor;
     53 import org.mockito.runners.MockitoJUnitRunner;
     54 
     55 @RunWith(MockitoJUnitRunner.class)
     56 public class JaegerExporterHandlerTest {
     57   private static final byte FF = (byte) 0xFF;
     58 
     59   private final HttpSender mockSender = mock(HttpSender.class);
     60   private final Process process = new Process("test");
     61   private final JaegerExporterHandler handler = new JaegerExporterHandler(mockSender, process);
     62 
     63   @Captor private ArgumentCaptor<List<Span>> captor;
     64 
     65   @Test
     66   public void exportShouldConvertFromSpanDataToJaegerThriftSpan() throws SenderException {
     67     final long startTime = 1519629870001L;
     68     final long endTime = 1519630148002L;
     69     final SpanData spanData =
     70         SpanData.create(
     71             sampleSpanContext(),
     72             SpanId.fromBytes(new byte[] {(byte) 0x7F, FF, FF, FF, FF, FF, FF, FF}),
     73             true,
     74             "test",
     75             Timestamp.fromMillis(startTime),
     76             SpanData.Attributes.create(sampleAttributes(), 0),
     77             SpanData.TimedEvents.create(singletonList(sampleAnnotation()), 0),
     78             SpanData.TimedEvents.create(singletonList(sampleMessageEvent()), 0),
     79             SpanData.Links.create(sampleLinks(), 0),
     80             0,
     81             Status.OK,
     82             Timestamp.fromMillis(endTime));
     83 
     84     handler.export(singletonList(spanData));
     85 
     86     verify(mockSender).send(eq(process), captor.capture());
     87     List<Span> spans = captor.getValue();
     88 
     89     assertThat(spans.size()).isEqualTo(1);
     90     Span span = spans.get(0);
     91 
     92     assertThat(span.operationName).isEqualTo("test");
     93     assertThat(span.spanId).isEqualTo(256L);
     94     assertThat(span.traceIdHigh).isEqualTo(-72057594037927936L);
     95     assertThat(span.traceIdLow).isEqualTo(1L);
     96     assertThat(span.parentSpanId).isEqualTo(Long.MAX_VALUE);
     97     assertThat(span.flags).isEqualTo(1);
     98     assertThat(span.startTime).isEqualTo(MILLISECONDS.toMicros(startTime));
     99     assertThat(span.duration).isEqualTo(MILLISECONDS.toMicros(endTime - startTime));
    100 
    101     assertThat(span.tags.size()).isEqualTo(3);
    102     assertThat(span.tags)
    103         .containsExactly(
    104             new Tag("BOOL", TagType.BOOL).setVBool(false),
    105             new Tag("LONG", TagType.LONG).setVLong(Long.MAX_VALUE),
    106             new Tag("STRING", TagType.STRING)
    107                 .setVStr(
    108                     "Judge of a man by his questions rather than by his answers. -- Voltaire"));
    109 
    110     assertThat(span.logs.size()).isEqualTo(1);
    111     Log log = span.logs.get(0);
    112     assertThat(log.timestamp).isEqualTo(1519629872987654L);
    113     assertThat(log.fields.size()).isEqualTo(4);
    114     assertThat(log.fields)
    115         .containsExactly(
    116             new Tag("description", TagType.STRING).setVStr("annotation #1"),
    117             new Tag("bool", TagType.BOOL).setVBool(true),
    118             new Tag("long", TagType.LONG).setVLong(1337L),
    119             new Tag("string", TagType.STRING)
    120                 .setVStr("Kind words do not cost much. Yet they accomplish much. -- Pascal"));
    121 
    122     assertThat(span.references.size()).isEqualTo(1);
    123     SpanRef reference = span.references.get(0);
    124     assertThat(reference.traceIdHigh).isEqualTo(-1L);
    125     assertThat(reference.traceIdLow).isEqualTo(-256L);
    126     assertThat(reference.spanId).isEqualTo(512L);
    127     assertThat(reference.refType).isEqualTo(SpanRefType.CHILD_OF);
    128   }
    129 
    130   private static SpanContext sampleSpanContext() {
    131     return SpanContext.create(
    132         TraceId.fromBytes(new byte[] {FF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}),
    133         SpanId.fromBytes(new byte[] {0, 0, 0, 0, 0, 0, 1, 0}),
    134         TraceOptions.builder().setIsSampled(true).build());
    135   }
    136 
    137   private static ImmutableMap<String, AttributeValue> sampleAttributes() {
    138     return ImmutableMap.of(
    139         "BOOL", AttributeValue.booleanAttributeValue(false),
    140         "LONG", AttributeValue.longAttributeValue(Long.MAX_VALUE),
    141         "STRING",
    142             AttributeValue.stringAttributeValue(
    143                 "Judge of a man by his questions rather than by his answers. -- Voltaire"));
    144   }
    145 
    146   private static SpanData.TimedEvent<Annotation> sampleAnnotation() {
    147     return SpanData.TimedEvent.create(
    148         Timestamp.create(1519629872L, 987654321),
    149         Annotation.fromDescriptionAndAttributes(
    150             "annotation #1",
    151             ImmutableMap.of(
    152                 "bool", AttributeValue.booleanAttributeValue(true),
    153                 "long", AttributeValue.longAttributeValue(1337L),
    154                 "string",
    155                     AttributeValue.stringAttributeValue(
    156                         "Kind words do not cost much. Yet they accomplish much. -- Pascal"))));
    157   }
    158 
    159   private static SpanData.TimedEvent<MessageEvent> sampleMessageEvent() {
    160     return SpanData.TimedEvent.create(
    161         Timestamp.create(1519629871L, 123456789),
    162         MessageEvent.builder(MessageEvent.Type.SENT, 42L).build());
    163   }
    164 
    165   private static List<Link> sampleLinks() {
    166     return Lists.newArrayList(
    167         Link.fromSpanContext(
    168             SpanContext.create(
    169                 TraceId.fromBytes(
    170                     new byte[] {FF, FF, FF, FF, FF, FF, FF, FF, FF, FF, FF, FF, FF, FF, FF, 0}),
    171                 SpanId.fromBytes(new byte[] {0, 0, 0, 0, 0, 0, 2, 0}),
    172                 TraceOptions.builder().setIsSampled(false).build()),
    173             Link.Type.CHILD_LINKED_SPAN,
    174             ImmutableMap.of(
    175                 "Bool", AttributeValue.booleanAttributeValue(true),
    176                 "Long", AttributeValue.longAttributeValue(299792458L),
    177                 "String",
    178                     AttributeValue.stringAttributeValue(
    179                         "Man is condemned to be free; because once thrown into the world, "
    180                             + "he is responsible for everything he does. -- Sartre"))));
    181   }
    182 }
    183