diff options
Diffstat (limited to 'kamon-core/src/test/scala/kamon/trace/TracerSpec.scala')
-rw-r--r-- | kamon-core/src/test/scala/kamon/trace/TracerSpec.scala | 154 |
1 files changed, 151 insertions, 3 deletions
diff --git a/kamon-core/src/test/scala/kamon/trace/TracerSpec.scala b/kamon-core/src/test/scala/kamon/trace/TracerSpec.scala index 686c15d0..3e05adb5 100644 --- a/kamon-core/src/test/scala/kamon/trace/TracerSpec.scala +++ b/kamon-core/src/test/scala/kamon/trace/TracerSpec.scala @@ -1,18 +1,166 @@ package kamon.trace +import com.typesafe.config.ConfigFactory import kamon.Kamon -import org.scalatest.{Matchers, WordSpec} +import kamon.testkit.{SpanBuilding, SpanInspector} +import kamon.trace.Span.TagValue +import kamon.trace.SpanContext.Source +import kamon.trace.SpanContextCodec.Format +import org.scalatest.{Matchers, OptionValues, WordSpec} -class TracerSpec extends WordSpec with Matchers { +class TracerSpec extends WordSpec with Matchers with SpanBuilding with OptionValues { "the Kamon tracer" should { - "build spans that contain all information given to the builder" in { + "construct a minimal Span that only has a operation name" in { + val span = tracer.buildSpan("myOperation").start() + val spanData = inspect(span) + + spanData.operationName() shouldBe "myOperation" + spanData.metricTags() shouldBe empty + spanData.spanTags() shouldBe empty + } + + "pass the operation name and tags to started Span" in { val span = tracer.buildSpan("myOperation") + .withMetricTag("metric-tag", "value") + .withMetricTag("metric-tag", "value") .withSpanTag("hello", "world") + .withSpanTag("kamon", "rulez") + .withSpanTag("number", 123) + .withSpanTag("boolean", true) .start() + + val spanData = inspect(span) + spanData.operationName() shouldBe "myOperation" + spanData.metricTags() should contain only ( + ("metric-tag" -> "value")) + + spanData.spanTags() should contain allOf( + ("hello" -> TagValue.String("world")), + ("kamon" -> TagValue.String("rulez")), + ("number" -> TagValue.Number(123)), + ("boolean" -> TagValue.True)) + } + + "do not interfere with the currently active Span if not requested when starting a Span" in { + val previouslyActiveSpan = tracer.activeSpan() + tracer.buildSpan("myOperation").start() + tracer.activeSpan() should be theSameInstanceAs(previouslyActiveSpan) + } + + "make a span active with started with the .startActive() function and restore the previous Span when deactivated" in { + val previouslyActiveSpan = tracer.activeSpan() + val activeSpan = tracer.buildSpan("myOperation").startActive() + + tracer.activeSpan() shouldNot be theSameInstanceAs(previouslyActiveSpan) + val activeSpanData = inspect(activeSpan) + activeSpanData.operationName() shouldBe "myOperation" + + activeSpan.deactivate() + tracer.activeSpan() should be theSameInstanceAs(previouslyActiveSpan) + } + + "not have any parent Span if there is ActiveSpan and no parent was explicitly given" in { + val span = tracer.buildSpan("myOperation").start() + val spanData = inspect(span) + spanData.context().parentID shouldBe IdentityProvider.NoIdentifier + } + + "use the currently active span as parent" in { + val parent = tracer.buildSpan("myOperation").startActive() + val child = tracer.buildSpan("childOperation").asChildOf(parent).start() + parent.deactivate() + + val parentData = inspect(parent) + val childData = inspect(child) + parentData.context().spanID shouldBe childData.context().parentID + } + + "ignore the currently active span as parent if explicitly requested" in { + val parent = tracer.buildSpan("myOperation").startActive() + val child = tracer.buildSpan("childOperation").ignoreActiveSpan().start() + parent.deactivate() + + val childData = inspect(child) + childData.context().parentID shouldBe IdentityProvider.NoIdentifier + } + + "allow overriding the start timestamp for a Span" in { + val span = tracer.buildSpan("myOperation").withStartTimestamp(100).start() + val spanData = inspect(span) + spanData.startTimestamp() shouldBe 100 } + + "inject and extract a SpanContext from a TextMap carrier" in { + val spanContext = createSpanContext() + val injected = Kamon.inject(spanContext, Format.TextMap) + val extractedSpanContext = Kamon.extract(Format.TextMap, injected).value + + spanContext.traceID shouldBe(extractedSpanContext.traceID) + spanContext.spanID shouldBe(extractedSpanContext.spanID) + spanContext.parentID shouldBe(extractedSpanContext.parentID) + spanContext.baggage.getAll() shouldBe(extractedSpanContext.baggage.getAll()) + } + + "inject and extract a SpanContext from a TextMap carrier supplied by the caller" in { + val spanContext = createSpanContext() + val carrier = TextMap.Default() + Kamon.inject(spanContext, Format.TextMap, carrier) + val extractedSpanContext = Kamon.extract(Format.TextMap, carrier).value + + spanContext.traceID shouldBe(extractedSpanContext.traceID) + spanContext.spanID shouldBe(extractedSpanContext.spanID) + spanContext.parentID shouldBe(extractedSpanContext.parentID) + spanContext.baggage.getAll() shouldBe(extractedSpanContext.baggage.getAll()) + } + + "inject and extract a SpanContext from a HttpHeaders carrier" in { + val spanContext = createSpanContext() + val injected = Kamon.inject(spanContext, Format.HttpHeaders) + val extractedSpanContext = Kamon.extract(Format.HttpHeaders, injected).value + + spanContext.traceID shouldBe(extractedSpanContext.traceID) + spanContext.spanID shouldBe(extractedSpanContext.spanID) + spanContext.parentID shouldBe(extractedSpanContext.parentID) + spanContext.baggage.getAll() shouldBe(extractedSpanContext.baggage.getAll()) + } + + "inject and extract a SpanContext from a HttpHeaders using a TextMap provided by the caller" in { + val spanContext = createSpanContext() + val carrier = TextMap.Default() + Kamon.inject(spanContext, Format.HttpHeaders, carrier) + val extractedSpanContext = Kamon.extract(Format.HttpHeaders, carrier).value + + spanContext.traceID shouldBe(extractedSpanContext.traceID) + spanContext.spanID shouldBe(extractedSpanContext.spanID) + spanContext.parentID shouldBe(extractedSpanContext.parentID) + spanContext.baggage.getAll() shouldBe(extractedSpanContext.baggage.getAll()) + } + + + "preserve the same Span and Parent identifier when creating a Span with a remote parent if join-remote-parents-with-same-span-id is enabled" in { + val previousConfig = Kamon.config() + + Kamon.reconfigure { + ConfigFactory.parseString("kamon.trace.join-remote-parents-with-same-span-id = yes") + .withFallback(Kamon.config()) + } + + val remoteParent = createSpanContext().copy(source = Source.Remote) + val childData = inspect(tracer.buildSpan("local").asChildOf(remoteParent).start()) + + childData.context().traceID shouldBe remoteParent.traceID + childData.context().parentID shouldBe remoteParent.parentID + childData.context().spanID shouldBe remoteParent.spanID + + Kamon.reconfigure(previousConfig) + } + } val tracer: Tracer = Kamon + def inspect(span: Span): SpanInspector = + SpanInspector(span) + } |