Permalink
Browse files

ui: replace json adapters with implicit conversions

Author: @franklinhu
Fixes #181
URL: #181
  • Loading branch information...
1 parent 0db0391 commit 17ad96cdbce9390ea8812a0a153c0bc7626c7f68 @franklinhu franklinhu committed with Franklin Hu Oct 18, 2012
@@ -1,65 +0,0 @@
-package com.twitter.zipkin.adapter
-
-import com.twitter.zipkin.common._
-import com.twitter.zipkin.common.json.{JsonBinaryAnnotation, JsonSpan}
-
-/**
- * Adapter to make common classes compatible with Jackson/Jerkson JSON generation
- */
-object JsonAdapter extends Adapter {
- type annotationType = Annotation
- type annotationTypeType = AnnotationType
- type binaryAnnotationType = JsonBinaryAnnotation
- type endpointType = Endpoint
- type spanType = JsonSpan
-
- /* No change between JSON and common types */
- def apply(a: annotationType): Annotation = a
- def apply(a: annotationTypeType): AnnotationType = a
- def apply(e: endpointType): Endpoint = e
-
- def apply(b: binaryAnnotationType): BinaryAnnotation = {
- throw new Exception("Not implemented")
- }
-
- def apply(b: BinaryAnnotation): binaryAnnotationType = {
- val value = b.annotationType match {
- case AnnotationType(0, _) => if (b.value.get() != 0) true else false // bool
- case AnnotationType(1, _) => new String(b.value.array(), b.value.position(), b.value.remaining()) // bytes
- case AnnotationType(2, _) => b.value.getShort // i16
- case AnnotationType(3, _) => b.value.getInt // i32
- case AnnotationType(4, _) => b.value.getLong // i64
- case AnnotationType(5, _) => b.value.getDouble // double
- case AnnotationType(6, _) => new String(b.value.array(), b.value.position(), b.value.remaining()) // string
- case _ => {
- throw new Exception("Uh oh")
- }
- }
- JsonBinaryAnnotation(b.key, value, b.annotationType, b.host)
- }
-
- def apply(s: spanType): Span = {
- Span(
- s.traceId.toLong,
- s.name,
- s.id.toLong,
- s.parentId.map(_.toLong),
- s.annotations,
- s.binaryAnnotations.map(JsonAdapter(_)))
- }
-
- def apply(s: Span): spanType = {
- JsonSpan(
- s.traceId.toString,
- s.name,
- s.id.toString,
- s.parentId.map(_.toString),
- s.serviceNames,
- s.firstAnnotation.map(_.timestamp),
- s.duration,
- s.annotations.sortWith((a,b) => a.timestamp < b.timestamp),
- s.binaryAnnotations.map(JsonAdapter(_)))
- }
-}
-
-
@@ -1,104 +0,0 @@
-package com.twitter.zipkin.adapter
-
-import com.twitter.zipkin.common.json._
-import com.twitter.zipkin.query._
-
-/**
- * JS doesn't like Longs so we need to convert them to strings
- */
-object JsonQueryAdapter extends QueryAdapter {
- type timelineAnnotationType = JsonTimelineAnnotation
- type traceTimelineType = JsonTraceTimeline
- type traceComboType = JsonTraceCombo
- type traceSummaryType = JsonTraceSummary
- type traceType = JsonTrace
-
- type queryRequestType = QueryRequest
- type queryResponseType = QueryResponse
-
- type orderType = Order
-
- /* no change between json and common */
- def apply(t: timelineAnnotationType): TimelineAnnotation = {
- TimelineAnnotation(t.timestamp, t.value, t.host, t.spanId.toLong, t.parentId.map(_.toLong), t.serviceName, t.spanName)
- }
-
- def apply(t: TimelineAnnotation): timelineAnnotationType = {
- JsonTimelineAnnotation(t.timestamp, t.value, t.host, t.spanId.toString, t.parentId.map(_.toString), t.serviceName, t.spanName)
- }
-
- /* json to common */
- def apply(t: traceTimelineType): TraceTimeline = {
- TraceTimeline(
- t.traceId.toLong,
- t.rootSpanId.toLong,
- t.annotations.map(JsonQueryAdapter(_)),
- t.binaryAnnotations.map(JsonAdapter(_)))
- }
-
- /* common to json */
- def apply(t: TraceTimeline): traceTimelineType = {
- JsonTraceTimeline(
- t.traceId.toString,
- t.rootSpanId.toString,
- t.annotations.map(JsonQueryAdapter(_)),
- t.binaryAnnotations.map(JsonAdapter(_)))
- }
-
- /* json to common */
- def apply(t: traceComboType): TraceCombo = {
- TraceCombo(
- JsonQueryAdapter(t.trace),
- t.traceSummary.map(JsonQueryAdapter(_)),
- t.traceTimeline.map(JsonQueryAdapter(_)),
- t.spanDepths)
- }
-
- /* common to json */
- def apply(t: TraceCombo): traceComboType = {
- JsonTraceCombo(
- JsonQueryAdapter(t.trace),
- t.traceSummary.map(JsonQueryAdapter(_)),
- t.traceTimeline.map(JsonQueryAdapter(_)),
- t.spanDepths)
- }
-
- def apply(t: traceSummaryType): TraceSummary = {
- TraceSummary(t.traceId.toLong, t.startTimestamp, t.endTimestamp, t.durationMicro, t.serviceCounts, t.endpoints)
- }
-
- def apply(t: TraceSummary): traceSummaryType = {
- JsonTraceSummary(t.traceId.toString, t.startTimestamp, t.endTimestamp, t.durationMicro, t.serviceCounts.toMap, t.endpoints)
- }
-
- /* json to common */
- def apply(t: traceType): Trace = {
- throw new Exception("NOT IMPLEMENTED")
- }
-
- /* common to json */
- def apply(t: Trace): traceType = {
- /**
- * TODO this is a pain in the ass, we need to fix common.Trace so the case class has the
- * necessary fields in the constructor
- */
- val startAndEnd = t.getStartAndEndTimestamp.get
- JsonTrace(
- t.id.map(_.toString).getOrElse(""),
- t.spans.map(JsonAdapter(_)),
- startAndEnd.start,
- startAndEnd.end,
- startAndEnd.end - startAndEnd.start,
- t.serviceCounts)
- }
-
- /* No-ops since not used */
- def apply(q: queryRequestType): QueryRequest = q
- //def apply(q: QueryRequest): queryRequestType = q
-
- def apply(q: queryResponseType): QueryResponse = q
- //def apply(q: QueryResponse): queryResponseType = q
-
- def apply(o: orderType): Order = o
- //def apply(o: Order): orderType = o
-}
@@ -17,5 +17,5 @@ package com.twitter.zipkin.common.json
import com.twitter.zipkin.common.Endpoint
-case class JsonTimelineAnnotation(timestamp: Long, value: String, host: Endpoint, spanId: String, parentId: Option[String],
+case class JsonTimelineAnnotation(timestamp: String, value: String, host: Endpoint, spanId: String, parentId: Option[String],
serviceName: String, spanName: String)
@@ -0,0 +1,99 @@
+package com.twitter.zipkin.conversions
+
+import com.twitter.zipkin.common.json._
+import com.twitter.zipkin.common._
+import com.twitter.zipkin.query._
+
+/**
+ * json doesn't like Longs, so we need to convert them to strings
+ */
+object json {
+
+ /* BinaryAnnotation */
+ class WrappedBinaryAnnotation(b: BinaryAnnotation) {
+ lazy val toJson = {
+ val value = b.annotationType match {
+ case AnnotationType(0, _) => if (b.value.get() != 0) true else false // bool
+ case AnnotationType(1, _) => new String(b.value.array(), b.value.position(), b.value.remaining()) // bytes
+ case AnnotationType(2, _) => b.value.getShort // i16
+ case AnnotationType(3, _) => b.value.getInt // i32
+ case AnnotationType(4, _) => b.value.getLong // i64
+ case AnnotationType(5, _) => b.value.getDouble // double
+ case AnnotationType(6, _) => new String(b.value.array(), b.value.position(), b.value.remaining()) // string
+ case _ => {
+ throw new Exception("Unsupported annotation type: %s".format(b))
+ }
+ }
+ JsonBinaryAnnotation(b.key, value, b.annotationType, b.host)
+ }
+ }
+ implicit def binaryAnnotationToJson(b: BinaryAnnotation) = new WrappedBinaryAnnotation(b)
+
+ /* Span */
+ class WrappedSpan(s: Span) {
+ lazy val toJson = {
+ JsonSpan(
+ s.traceId.toString,
+ s.name,
+ s.id.toString,
+ s.parentId.map(_.toString),
+ s.serviceNames,
+ s.firstAnnotation.map(_.timestamp),
+ s.duration,
+ s.annotations.sortWith((a,b) => a.timestamp < b.timestamp),
+ s.binaryAnnotations.map(_.toJson))
+ }
+ }
+ implicit def spanToJson(s: Span) = new WrappedSpan(s)
+
+ /* TimelineAnnotation */
+ class WrappedTimelineAnnotation(t: TimelineAnnotation) {
+ lazy val toJson = {
+ JsonTimelineAnnotation(t.timestamp.toString, t.value, t.host, t.spanId.toString, t.parentId map { _.toString }, t.serviceName, t.spanName)
+ }
+ }
+ implicit def timelineAnnotationToJson(t: TimelineAnnotation) = new WrappedTimelineAnnotation(t)
+
+ /* Trace */
+ class WrappedTrace(t: Trace) {
+ lazy val toJson = {
+ /**
+ * TODO this is a pain in the ass, we need to fix common.Trace so the case class has the
+ * necessary fields in the constructor
+ */
+ val startAndEnd = t.getStartAndEndTimestamp.get
+ JsonTrace(
+ t.id map { _.toString } getOrElse "",
+ t.spans map { _.toJson },
+ startAndEnd.start,
+ startAndEnd.end,
+ startAndEnd.end - startAndEnd.start,
+ t.serviceCounts)
+ }
+ }
+ implicit def traceToJson(t: Trace) = new WrappedTrace(t)
+
+ /* TraceTimeline */
+ class WrappedTraceTimeline(t: TraceTimeline) {
+ lazy val toJson = {
+ JsonTraceTimeline(t.traceId.toString, t.rootSpanId.toString, t.annotations map { _.toJson }, t.binaryAnnotations map { _.toJson })
+ }
+ }
+ implicit def traceTimelineToJson(t: TraceTimeline) = new WrappedTraceTimeline(t)
+
+ /* TraceSummary */
+ class WrappedTraceSummary(t: TraceSummary) {
+ lazy val toJson = {
+ JsonTraceSummary(t.traceId.toString, t.startTimestamp, t.endTimestamp, t.durationMicro, t.serviceCounts.toMap, t.endpoints)
+ }
+ }
+ implicit def traceSummaryToJson(t: TraceSummary) = new WrappedTraceSummary(t)
+
+ /* TraceCombo */
+ class WrappedTraceCombo(t: TraceCombo) {
+ lazy val toJson = {
+ JsonTraceCombo(t.trace.toJson, t.traceSummary map { _.toJson }, t.traceTimeline map { _.toJson }, t.spanDepths)
+ }
+ }
+ implicit def traceComboToJson(t: TraceCombo) = new WrappedTraceCombo(t)
+}
@@ -20,11 +20,12 @@ import com.codahale.jerkson.Json
import com.twitter.finatra.{Response, Controller, View, Request}
import com.twitter.logging.Logger
import com.twitter.util.Future
-import com.twitter.zipkin.adapter.{JsonQueryAdapter, ThriftQueryAdapter}
+import com.twitter.zipkin.adapter.ThriftQueryAdapter
import com.twitter.zipkin.gen
import com.twitter.zipkin.config.ZipkinWebConfig
import java.text.SimpleDateFormat
import java.util.Calendar
+import com.twitter.zipkin.conversions.json._
import com.twitter.zipkin.common.json.JsonTraceSummary
import com.twitter.zipkin.query.QueryRequest
@@ -138,7 +139,7 @@ class App(config: ZipkinWebConfig, client: gen.ZipkinQuery.FinagledClient) exten
case ids @ _ => {
client.getTraceSummariesByIds(ids, adjusters).map {
_.map { summary =>
- JsonQueryAdapter(ThriftQueryAdapter(summary))
+ ThriftQueryAdapter(summary).toJson
}
}
}
@@ -232,7 +233,7 @@ class App(config: ZipkinWebConfig, client: gen.ZipkinQuery.FinagledClient) exten
log.debug(ids.toString())
client.getTraceCombosByIds(ids, adjusters).map { _.map { ThriftQueryAdapter(_) }.head }.map { combo =>
- render.json(JsonQueryAdapter(combo))
+ render.json(combo.toJson)
}
}
@@ -247,7 +248,7 @@ class App(config: ZipkinWebConfig, client: gen.ZipkinQuery.FinagledClient) exten
ThriftQueryAdapter(_).trace
}.head
}.map { trace =>
- render.json(JsonQueryAdapter(trace))
+ render.json(trace.toJson)
}
}
@@ -1,27 +1,12 @@
-/*
- * 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
+package com.twitter.zipkin.conversions
import com.twitter.zipkin.common.{AnnotationType, BinaryAnnotation}
+import com.twitter.zipkin.conversions.json._
import java.nio.ByteBuffer
import org.specs.Specification
-import org.specs.mock.{ClassMocker, JMocker}
-class JsonAdapterSpec extends Specification with JMocker with ClassMocker {
+class JsonSpec extends Specification {
+
"JsonAdapter" should {
"convert binary annotations" in {
val key = "key"
@@ -30,40 +15,40 @@ class JsonAdapterSpec extends Specification with JMocker with ClassMocker {
val trueAnnotation = BinaryAnnotation(key, ByteBuffer.wrap(Array[Byte](1)), AnnotationType.Bool, None)
val falseAnnotation = BinaryAnnotation(key, ByteBuffer.wrap(Array[Byte](0)), AnnotationType.Bool, None)
- val trueConvert = JsonAdapter(trueAnnotation)
+ val trueConvert = trueAnnotation.toJson
trueConvert.value must_== true
- val falseConvert = JsonAdapter(falseAnnotation)
+ val falseConvert = falseAnnotation.toJson
falseConvert.value must_== false
}
"short" in {
val ann = BinaryAnnotation(key, ByteBuffer.allocate(2).putShort(0, 5.toShort), AnnotationType.I16, None)
- val convert = JsonAdapter(ann)
+ val convert = ann.toJson
convert.value must_== 5
}
"int" in {
val ann = BinaryAnnotation(key, ByteBuffer.allocate(4).putInt(0, 6), AnnotationType.I32, None)
- val convert = JsonAdapter(ann)
+ val convert = ann.toJson
convert.value must_== 6
}
"long" in {
val ann = BinaryAnnotation(key, ByteBuffer.allocate(8).putLong(0, 99999999999L), AnnotationType.I64, None)
- val convert = JsonAdapter(ann)
+ val convert = ann.toJson
convert.value must_== 99999999999L
}
"double" in {
val ann = BinaryAnnotation(key, ByteBuffer.allocate(8).putDouble(0, 1.3496), AnnotationType.Double, None)
- val convert = JsonAdapter(ann)
+ val convert = ann.toJson
convert.value must_== 1.3496
}
"string" in {
val ann = BinaryAnnotation(key, ByteBuffer.wrap("HELLO!".getBytes), AnnotationType.String, None)
- val convert = JsonAdapter(ann)
+ val convert = ann.toJson
convert.value must_== "HELLO!"
}
}
Oops, something went wrong.

0 comments on commit 17ad96c

Please sign in to comment.