Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Trace to zipkin-common (part 1) #66

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,29 @@
/*
* Copyright 2012 Twitter Inc.
*
* Licensed 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 com.twitter.zipkin.adapter

import com.twitter.zipkin.query.{TraceTimeline, TimelineAnnotation}

trait QueryAdapter {
type timelineAnnotationType /* corresponds to com.twitter.zipkin.query.TimelineAnnotation */
type traceTimelineType /* corresponds to com.twitter.zipkin.query.TraceTimeline */

def apply(t: timelineAnnotationType): TimelineAnnotation
def apply(t: TimelineAnnotation): timelineAnnotationType

def apply(t: traceTimelineType): TraceTimeline
def apply(t: TraceTimeline): traceTimelineType
}
@@ -0,0 +1,21 @@
/*
* Copyright 2012 Twitter Inc.
*
* Licensed 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 com.twitter.zipkin.query

import com.twitter.zipkin.common.Endpoint

case class TimelineAnnotation(timestamp: Long, value: String, host: Endpoint, spanId: Long, parentId: Option[Long],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a comment here and on the TraceTimeline that explains what it is

serviceName: String, spanName: String)
@@ -0,0 +1,21 @@
/*
* Copyright 2012 Twitter Inc.
*
* Licensed 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 com.twitter.zipkin.query

import com.twitter.zipkin.common.BinaryAnnotation

case class TraceTimeline(traceId: Long, rootSpanId: Long, annotations: Seq[TimelineAnnotation],
binaryAnnotations: Seq[BinaryAnnotation])
@@ -0,0 +1,66 @@
/*
* Copyright 2012 Twitter Inc.
*
* Licensed 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 com.twitter.zipkin.adapter

import com.twitter.zipkin.gen
import com.twitter.zipkin.query.{TraceTimeline, TimelineAnnotation}

object ThriftQueryAdapter extends QueryAdapter {
type timelineAnnotationType = gen.TimelineAnnotation
type traceTimelineType = gen.TraceTimeline

/* TimelineAnnotation from Thrift */
def apply(t: timelineAnnotationType): TimelineAnnotation = {
TimelineAnnotation(
t.`timestamp`,
t.`value`,
ThriftAdapter(t.`host`),
t.`spanId`,
t.`parentId`,
t.`serviceName`,
t.`spanName`)
}

/* TimelineAnnotation to Thrift */
def apply(t: TimelineAnnotation): timelineAnnotationType = {
gen.TimelineAnnotation(
t.timestamp,
t.value,
ThriftAdapter(t.host),
t.spanId,
t.parentId,
t.serviceName,
t.spanName)
}

/* TraceTimeline from Thrift */
def apply(t: traceTimelineType): TraceTimeline = {
TraceTimeline(
t.`traceId`,
t.`rootMostSpanId`,
t.`annotations`.map { ThriftQueryAdapter(_) },
t.`binaryAnnotations`.map { ThriftAdapter(_) })
}

/* TraceTimeline to Thrift */
def apply(t: TraceTimeline): traceTimelineType = {
gen.TraceTimeline(
t.traceId,
t.rootSpanId,
t.annotations.map { ThriftQueryAdapter(_) },
t.binaryAnnotations.map { ThriftAdapter(_) })
}
}
19 changes: 8 additions & 11 deletions zipkin-server/src/main/scala/com/twitter/zipkin/common/Trace.scala
Expand Up @@ -19,11 +19,12 @@ package com.twitter.zipkin.common
import com.twitter.zipkin.gen
import collection.mutable
import mutable.HashMap
import com.twitter.zipkin.query.conversions.TraceToTimeline
import com.twitter.logging.Logger
import java.nio.ByteBuffer
import com.twitter.zipkin.adapter.ThriftAdapter
import com.twitter.finagle.tracing.{Trace => FTrace}
import com.twitter.zipkin.query.conversions.TraceToTimeline
import com.twitter.zipkin.adapter.{ThriftQueryAdapter, ThriftAdapter}
import com.twitter.zipkin.query.TraceTimeline

/**
* Represents a trace, a bundle of spans.
Expand All @@ -49,8 +50,6 @@ case class Trace(spans: Seq[Span]) {

val log = Logger.get(getClass.getName)

private[this] val traceToTimeline = new TraceToTimeline

/**
* Find the trace id for this trace.
* Returns none if we have no spans to look up id by
Expand Down Expand Up @@ -150,13 +149,13 @@ case class Trace(spans: Seq[Span]) {
serviceCounts, endpoints.toList)
}

def toTimeline: Option[gen.TraceTimeline] = {
def toTimeline: Option[TraceTimeline] = {
FTrace.record("toTimeline")
traceToTimeline.toTraceTimeline(this)
TraceToTimeline(this)
}

def toTraceCombo: gen.TraceCombo = {
gen.TraceCombo(toThrift, toTraceSummary.map(ThriftAdapter(_)), toTimeline, toSpanDepths)
gen.TraceCombo(toThrift, toTraceSummary.map(ThriftAdapter(_)), toTimeline.map(ThriftQueryAdapter(_)), toSpanDepths)
}

/**
Expand Down Expand Up @@ -187,11 +186,9 @@ case class Trace(spans: Seq[Span]) {
/**
* Get all the binary annotations in this trace.
*/
def getBinaryAnnotations: Seq[gen.BinaryAnnotation] = {
def getBinaryAnnotations: Seq[BinaryAnnotation] = {
spans.map {
_.binaryAnnotations.map {
ThriftAdapter(_)
}
_.binaryAnnotations
}.flatten
}

Expand Down
Expand Up @@ -28,7 +28,7 @@ import com.twitter.zipkin.storage.{Aggregates, TraceIdDuration, Index, Storage}
import java.nio.ByteBuffer
import org.apache.thrift.TException
import scala.collection.Set
import com.twitter.zipkin.adapter.ThriftAdapter
import com.twitter.zipkin.adapter.{ThriftQueryAdapter, ThriftAdapter}

/**
* Able to respond to users queries regarding the traces. Usually does so
Expand Down Expand Up @@ -202,7 +202,7 @@ class QueryService(storage: Storage, index: Index, aggregates: Aggregates, adjus

Stats.timeFutureMillis("query.getTraceTimelinesByIds") {
storage.getTracesByIds(traceIds).map { id =>
id.flatMap(adjusters.foldLeft(_)((trace, adjuster) => adjuster.adjust(trace)).toTimeline)
id.flatMap(adjusters.foldLeft(_)((trace, adjuster) => adjuster.adjust(trace)).toTimeline.map(ThriftQueryAdapter(_)))
} rescue {
case e: Exception =>
log.error(e, "getTraceTimelinesByIds query failed")
Expand Down
Expand Up @@ -15,13 +15,12 @@
*/
package com.twitter.zipkin.query.conversions

import com.twitter.zipkin.gen
import com.twitter.zipkin.common.{IncompleteTraceDataException, Endpoint, Trace}
import com.twitter.zipkin.adapter.ThriftAdapter
import com.twitter.zipkin.common._
import com.twitter.zipkin.query.{TraceTimeline, TimelineAnnotation}

class TraceToTimeline {
object TraceToTimeline {

def toTraceTimeline(trace: Trace): Option[gen.TraceTimeline] = {
def apply(trace: Trace): Option[TraceTimeline] = {

if (trace.spans.isEmpty) {
return None
Expand All @@ -30,16 +29,18 @@ class TraceToTimeline {
// convert span and annotation to timeline annotation
val annotations = trace.spans.flatMap(s =>
s.annotations.map{ a =>
gen.TimelineAnnotation(a.timestamp, a.value,
TimelineAnnotation(
a.timestamp,
a.value,
a.host match {
case Some(s) => ThriftAdapter(s)
case None => ThriftAdapter(Endpoint.Unknown)
case Some(s) => s
case None => Endpoint.Unknown
},
s.id,
s.parentId,
a.host match {
case Some(s) => s.serviceName
case None => "Unknown"
case None => "Unknown"
},
s.name)
}
Expand All @@ -53,7 +54,7 @@ class TraceToTimeline {
val rootSpanId = trace.getRootMostSpan.getOrElse(return None).id
val id = trace.id.getOrElse(return None)

Some(gen.TraceTimeline(id, rootSpanId, annotations, trace.getBinaryAnnotations))
Some(TraceTimeline(id, rootSpanId, annotations, trace.getBinaryAnnotations))
}

}
}
Expand Up @@ -119,10 +119,10 @@ class TraceSpec extends Specification {
}

"getBinaryAnnotations" in {
val ba1 = gen.BinaryAnnotation("key1", ByteBuffer.wrap("value1".getBytes), gen.AnnotationType.String)
val span1 = Span(1L, "", 1L, None, List(), List(ThriftAdapter(ba1)))
val ba2 = gen.BinaryAnnotation("key2", ByteBuffer.wrap("value2".getBytes), gen.AnnotationType.String)
val span2 = Span(1L, "", 2L, None, List(), List(ThriftAdapter(ba2)))
val ba1 = BinaryAnnotation("key1", ByteBuffer.wrap("value1".getBytes), ThriftAdapter(gen.AnnotationType.String), None)
val span1 = Span(1L, "", 1L, None, List(), List(ba1))
val ba2 = BinaryAnnotation("key2", ByteBuffer.wrap("value2".getBytes), ThriftAdapter(gen.AnnotationType.String), None)
val span2 = Span(1L, "", 2L, None, List(), List(ba2))

val trace = Trace(List[Span](span1, span2))
Seq(ba1, ba2) mustEqual trace.getBinaryAnnotations
Expand Down
Expand Up @@ -25,8 +25,8 @@ import com.twitter.zipkin.common._
import java.nio.ByteBuffer
import com.twitter.util.Future
import com.twitter.scrooge.BinaryThriftStructSerializer
import com.twitter.zipkin.adapter.ThriftAdapter
import com.twitter.zipkin.storage.{Aggregates, TraceIdDuration, Storage, Index}
import com.twitter.zipkin.adapter.{ThriftQueryAdapter, ThriftAdapter}

class QueryServiceSpec extends Specification with JMocker with ClassMocker {
val ep1 = Endpoint(123, 123, "service1")
Expand Down Expand Up @@ -181,7 +181,7 @@ class QueryServiceSpec extends Specification with JMocker with ClassMocker {
}
val trace = trace1.toThrift
val summary = ThriftAdapter(TraceSummary(1, 100, 150, 50, Map("service1" -> 1), List(ep1)))
val timeline = trace1.toTimeline
val timeline = trace1.toTimeline.map(ThriftQueryAdapter(_))
val combo = gen.TraceCombo(trace, Some(summary), timeline, Some(Map(666L -> 1)))
Seq(combo) mustEqual qs.getTraceCombosByIds(List(traceId), List())()
}
Expand Down
Expand Up @@ -18,11 +18,12 @@ package com.twitter.zipkin.query.conversions
import org.specs.Specification
import org.specs.mock.{ClassMocker, JMocker}
import com.twitter.zipkin.gen
import com.twitter.zipkin.common.{Trace, Span, Annotation, Endpoint}

import scala.collection.JavaConversions._
import java.nio.ByteBuffer
import com.twitter.zipkin.adapter.ThriftAdapter
import com.twitter.zipkin.query.{TimelineAnnotation, TraceTimeline}
import com.twitter.zipkin.common._

class TraceToTimelineSpec extends Specification with JMocker with ClassMocker {

Expand Down Expand Up @@ -60,9 +61,9 @@ class TraceToTimelineSpec extends Specification with JMocker with ClassMocker {
val endpoint2 = Some(Endpoint(2, 2, cassieName)) //54147
val endpoint3 = Some(Endpoint(3, 3, koalabirdName)) //36516

val et1 = ThriftAdapter(endpoint1.get)
val et2 = ThriftAdapter(endpoint2.get)
val et3 = ThriftAdapter(endpoint3.get)
val et1 = endpoint1.get
val et2 = endpoint2.get
val et3 = endpoint3.get

// This is from a real trace, at least what the data would look like
// after being run through the TimeSkewAdjuster
Expand All @@ -73,10 +74,10 @@ class TraceToTimelineSpec extends Specification with JMocker with ClassMocker {
val ann5 = Annotation(85, gen.Constants.CLIENT_RECV, endpoint2)
val ann6 = Annotation(87, gen.Constants.CLIENT_RECV, endpoint3)

val ba1 = gen.BinaryAnnotation("key1", ByteBuffer.wrap("value1".getBytes), gen.AnnotationType.String)
val ba1 = BinaryAnnotation("key1", ByteBuffer.wrap("value1".getBytes), ThriftAdapter(gen.AnnotationType.String), None)

val span1 = Span(1, "ValuesFromSource", 2209720933601260005L, None,
List(ann3, ann6), List(ThriftAdapter(ba1)))
List(ann3, ann6), List(ba1))
val span2 = Span(1, "ValuesFromSource", 2209720933601260005L, None,
List(ann4, ann1), Nil)
// the above two spans are part of the same actual span
Expand All @@ -86,32 +87,30 @@ class TraceToTimelineSpec extends Specification with JMocker with ClassMocker {
val trace = new Trace(List(span1, span2, span3))

// annotation numbers match those above, order in list should not though
val tAnn1 = gen.TimelineAnnotation(1, gen.Constants.SERVER_RECV, et1,
val tAnn1 = TimelineAnnotation(1, gen.Constants.SERVER_RECV, et1,
2209720933601260005L, None, cuckooName, "ValuesFromSource")
val tAnn2 = gen.TimelineAnnotation(1, gen.Constants.CLIENT_SEND, et2,
val tAnn2 = TimelineAnnotation(1, gen.Constants.CLIENT_SEND, et2,
-855543208864892776L, Some(2209720933601260005L), cassieName, "multiget_slice")
val tAnn3 = gen.TimelineAnnotation(1, gen.Constants.CLIENT_SEND, et3,
val tAnn3 = TimelineAnnotation(1, gen.Constants.CLIENT_SEND, et3,
2209720933601260005L, None, koalabirdName, "ValuesFromSource")
val tAnn4 = gen.TimelineAnnotation(86, gen.Constants.SERVER_SEND, et1,
val tAnn4 = TimelineAnnotation(86, gen.Constants.SERVER_SEND, et1,
2209720933601260005L, None, cuckooName, "ValuesFromSource")
val tAnn5 = gen.TimelineAnnotation(85, gen.Constants.CLIENT_RECV, et2,
val tAnn5 = TimelineAnnotation(85, gen.Constants.CLIENT_RECV, et2,
-855543208864892776L, Some(2209720933601260005L), cassieName, "multiget_slice")
val tAnn6 = gen.TimelineAnnotation(87, gen.Constants.CLIENT_RECV, et3,
val tAnn6 = TimelineAnnotation(87, gen.Constants.CLIENT_RECV, et3,
2209720933601260005L, None, koalabirdName, "ValuesFromSource")

val expectedTimeline = gen.TraceTimeline(1, 2209720933601260005L, List(tAnn3, tAnn1, tAnn2,
val expectedTimeline = TraceTimeline(1, 2209720933601260005L, List(tAnn3, tAnn1, tAnn2,
tAnn5, tAnn4, tAnn6), List(ba1))

val traceToTimeline = new TraceToTimeline

"TraceToTimelineSpec" should {
"convert to timeline with correct annotations ordering" in {
val actualTimeline = traceToTimeline.toTraceTimeline(trace)
val actualTimeline = TraceToTimeline(trace)
Some(expectedTimeline) mustEqual actualTimeline
}

"return none if empty trace" in {
val actualTimeline = traceToTimeline.toTraceTimeline(new Trace(List()))
val actualTimeline = TraceToTimeline(new Trace(List()))
None mustEqual actualTimeline
}
}
Expand Down