diff --git a/zipkin-common/src/main/scala/com/twitter/zipkin/common/Span.scala b/zipkin-common/src/main/scala/com/twitter/zipkin/common/Span.scala index 15a4d6e8bf4..414ec3d201a 100644 --- a/zipkin-common/src/main/scala/com/twitter/zipkin/common/Span.scala +++ b/zipkin-common/src/main/scala/com/twitter/zipkin/common/Span.scala @@ -21,7 +21,7 @@ import com.twitter.zipkin.Constants /** * A span represents one RPC request. A trace is made up of many spans. * - * A span can contain multiple annotations, some are always incuded such as + * A span can contain multiple annotations, some are always included such as * Client send -> Server received -> Server send -> Client receive. * * Some are created by users, describing application specific information, @@ -30,7 +30,7 @@ import com.twitter.zipkin.Constants object Span { def apply(span: Span): Span = Span(span.traceId, span.name, span.id, - span.parentId, span.annotations, span.binaryAnnotations) + span.parentId, span.annotations, span.binaryAnnotations, span.debug) } /** @@ -42,9 +42,10 @@ object Span { * some fixed ones from the tracing framework * @param binaryAnnotations binary annotations, can contain more detailed information such as * serialized objects + * @param debug if this is set we will make sure this span is stored, no matter what the samplers want */ case class Span(traceId: Long, name: String, id: Long, parentId: Option[Long], - annotations: List[Annotation], binaryAnnotations: Seq[BinaryAnnotation]) { + annotations: List[Annotation], binaryAnnotations: Seq[BinaryAnnotation], debug: Boolean = false) { /** * Order annotations by timestamp. */ @@ -96,7 +97,7 @@ case class Span(traceId: Long, name: String, id: Long, parentId: Option[Long], new Span(traceId, selectedName, id, parentId, annotations ++ mergeFrom.annotations, - binaryAnnotations ++ mergeFrom.binaryAnnotations) + binaryAnnotations ++ mergeFrom.binaryAnnotations, debug | mergeFrom.debug) } /** diff --git a/zipkin-common/src/test/scala/com/twitter/zipkin/common/SpanSpec.scala b/zipkin-common/src/test/scala/com/twitter/zipkin/common/SpanSpec.scala index 38209ccaa26..1b68f68754a 100644 --- a/zipkin-common/src/test/scala/com/twitter/zipkin/common/SpanSpec.scala +++ b/zipkin-common/src/test/scala/com/twitter/zipkin/common/SpanSpec.scala @@ -52,9 +52,9 @@ class SpanSpec extends Specification { val ann1 = Annotation(1, "value1", Some(Endpoint(1, 2, "service"))) val ann2 = Annotation(2, "value2", Some(Endpoint(3, 4, "service"))) - val span1 = Span(12345, "", 666, None, List(ann1), Nil) - val span2 = Span(12345, "methodcall", 666, None, List(ann2), Nil) - val expectedSpan = Span(12345, "methodcall", 666, None, List(ann1, ann2), Nil) + val span1 = Span(12345, "", 666, None, List(ann1), Nil, true) + val span2 = Span(12345, "methodcall", 666, None, List(ann2), Nil, false) + val expectedSpan = Span(12345, "methodcall", 666, None, List(ann1, ann2), Nil, true) val actualSpan = span1.mergeSpan(span2) actualSpan mustEqual expectedSpan } diff --git a/zipkin-scribe/src/test/scala/com/twitter/zipkin/collector/ScribeCollectorServiceSpec.scala b/zipkin-scribe/src/test/scala/com/twitter/zipkin/collector/ScribeCollectorServiceSpec.scala index ef54517cf42..682d803be82 100644 --- a/zipkin-scribe/src/test/scala/com/twitter/zipkin/collector/ScribeCollectorServiceSpec.scala +++ b/zipkin-scribe/src/test/scala/com/twitter/zipkin/collector/ScribeCollectorServiceSpec.scala @@ -38,7 +38,7 @@ class ScribeCollectorServiceSpec extends Specification with JMocker with ClassMo val wrongCatList = List(gen.LogEntry("wrongcat", serializer.toString(ThriftAdapter(validSpan)))) - val base64 = "CgABAAAAAAAAAHsLAAMAAAADYm9vCgAEAAAAAAAAAcgPAAYMAAAAAQoAAQAAAAAAAAABCwACAAAAA2JhaAAPAAgMAAAAAAA=" + val base64 = "CgABAAAAAAAAAHsLAAMAAAADYm9vCgAEAAAAAAAAAcgPAAYMAAAAAQoAAQAAAAAAAAABCwACAAAAA2JhaAAPAAgMAAAAAAIACQAA" val queue = mock[WriteQueue[Seq[String]]] val zkSampleRateConfig = mock[AdjustableRateConfig] diff --git a/zipkin-scrooge/src/main/scala/com/twitter/zipkin/adapter/ThriftAdapter.scala b/zipkin-scrooge/src/main/scala/com/twitter/zipkin/adapter/ThriftAdapter.scala index 101089cb445..a28c44a3055 100644 --- a/zipkin-scrooge/src/main/scala/com/twitter/zipkin/adapter/ThriftAdapter.scala +++ b/zipkin-scrooge/src/main/scala/com/twitter/zipkin/adapter/ThriftAdapter.scala @@ -108,13 +108,13 @@ object ThriftAdapter extends Adapter { case b => b.map { this(_) } } - new Span(s.traceId, s.name, s.id, s.parentId, annotations, binaryAnnotations) + new Span(s.traceId, s.name, s.id, s.parentId, annotations, binaryAnnotations, s.debug) } /* Span to Thrift */ def apply(s: Span): spanType = { gen.Span(s.traceId, s.name, s.id, s.parentId, s.annotations.map { this(_) }, - s.binaryAnnotations.map { this(_) }) + s.binaryAnnotations.map { this(_) }, s.debug) } /* TraceSummary from Thrift */ diff --git a/zipkin-server/src/main/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilter.scala b/zipkin-server/src/main/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilter.scala index 0d763685e45..19e26371343 100644 --- a/zipkin-server/src/main/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilter.scala +++ b/zipkin-server/src/main/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilter.scala @@ -29,7 +29,14 @@ class SamplerProcessorFilter(sampler: GlobalSampler) extends ProcessorFilter[Seq spans.flatMap { span => span.serviceNames.foreach { name => Stats.incr("received_" + name) } - if (sampler(span.traceId)) { + /** + * If the span was created with debug mode on we guarantee that it will be + * stored no matter what our sampler tells us + */ + if (span.debug) { + Stats.incr("debugflag") + Some(span) + } else if (sampler(span.traceId)) { Some(span) } else { None diff --git a/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/EverythingGlobalSampler.scala b/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/EverythingGlobalSampler.scala deleted file mode 100644 index aed8b0a60a1..00000000000 --- a/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/EverythingGlobalSampler.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.collector.sampler - -/** - * Let through everything. - */ -object EverythingGlobalSampler extends GlobalSampler { - override def apply(traceId: Long): Boolean = true -} diff --git a/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/GlobalSampler.scala b/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/GlobalSampler.scala index 501ab2982de..2af0ed9b094 100644 --- a/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/GlobalSampler.scala +++ b/zipkin-server/src/main/scala/com/twitter/zipkin/collector/sampler/GlobalSampler.scala @@ -36,6 +36,20 @@ trait GlobalSampler { * True: drop trace on the floor * False: process trace */ - def apply(traceId: Long) : Boolean = false + def apply(traceId: Long): Boolean = false } + +/** + * None shall pass! Drop all the trace data. + */ +object NullGlobalSampler extends GlobalSampler { + override def apply(traceId: Long) = false +} + +/** + * Let everything through. + */ +object EverythingGlobalSampler extends GlobalSampler { + override def apply(traceId: Long) = true +} diff --git a/zipkin-server/src/test/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilterSpec.scala b/zipkin-server/src/test/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilterSpec.scala new file mode 100644 index 00000000000..92b4fa383ca --- /dev/null +++ b/zipkin-server/src/test/scala/com/twitter/zipkin/collector/processor/SamplerProcessorFilterSpec.scala @@ -0,0 +1,50 @@ +package com.twitter.zipkin.collector.processor + +/* + * 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. + * + */ + +import org.specs.Specification +import com.twitter.zipkin.gen +import com.twitter.zipkin.common.{Span, Endpoint, Annotation} +import com.twitter.ostrich.stats.{Histogram, Distribution, Stats} +import com.twitter.zipkin.collector.sampler.{EverythingGlobalSampler, NullGlobalSampler} + +class SamplerProcessorFilterSpec extends Specification { + + "SamplerProcessorFilter" should { + "let the span pass if debug flag is set" in { + val span = Span(12345, "methodcall", 666, None, List(), Nil, true) + val spans = Seq(span) + val samplerProcessor = new SamplerProcessorFilter(NullGlobalSampler) + samplerProcessor(spans) mustEqual spans + } + + "let the span pass if debug flag false and sampler says yes" in { + val span = Span(12345, "methodcall", 666, None, List(), Nil, false) + val spans = Seq(span) + val samplerProcessor = new SamplerProcessorFilter(EverythingGlobalSampler) + samplerProcessor(spans) mustEqual spans + } + + "don't let the span pass if debug flag false and sampler says no" in { + val span = Span(12345, "methodcall", 666, None, List(), Nil, false) + val spans = Seq(span) + val samplerProcessor = new SamplerProcessorFilter(NullGlobalSampler) + samplerProcessor(spans) mustEqual Seq() + } + } +} diff --git a/zipkin-test/src/test/resources/TestCollector.scala b/zipkin-test/src/test/resources/TestCollector.scala index 29c8759a58f..ddc9fb8f57d 100644 --- a/zipkin-test/src/test/resources/TestCollector.scala +++ b/zipkin-test/src/test/resources/TestCollector.scala @@ -16,7 +16,7 @@ import com.twitter.zipkin.config._ import com.twitter.zipkin.config.sampler.NullAdaptiveSamplerConfig import com.twitter.zipkin.config.zookeeper.ZooKeeperConfig -import com.twitter.zipkin.collector.sampler.GlobalSampler +import com.twitter.zipkin.collector.sampler.{GlobalSampler, EverythingGlobalSampler} import com.twitter.conversions.time._ import com.twitter.logging.LoggerFactory import com.twitter.logging.config._ @@ -64,9 +64,7 @@ new ScribeZipkinCollectorConfig { override def adaptiveSamplerConfig = new NullAdaptiveSamplerConfig {} // sample it all - override def globalSampler: GlobalSampler = new GlobalSampler() { - override def apply(traceId: Long) : Boolean = true - } + override def globalSampler: GlobalSampler = EverythingGlobalSampler def zkConfig = new ZooKeeperConfig { servers = List("localhost:2181") diff --git a/zipkin-thrift/src/main/thrift/zipkinCore.thrift b/zipkin-thrift/src/main/thrift/zipkinCore.thrift index 1c78250d67a..a14b8887ef8 100755 --- a/zipkin-thrift/src/main/thrift/zipkinCore.thrift +++ b/zipkin-thrift/src/main/thrift/zipkinCore.thrift @@ -53,4 +53,6 @@ struct Span { 5: optional i64 parent_id, // parent span id 6: list annotations, // list of all annotations/events that occured 8: list binary_annotations // any binary annotations + 9: optional bool debug = 0 // if true, we DEMAND that this span passes all samplers } +